diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_film.h')
-rw-r--r-- | intern/cycles/kernel/kernel_film.h | 532 |
1 files changed, 0 insertions, 532 deletions
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h deleted file mode 100644 index a87eff3832e..00000000000 --- a/intern/cycles/kernel/kernel_film.h +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright 2011-2013 Blender Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -CCL_NAMESPACE_BEGIN - -/* -------------------------------------------------------------------- - * Common utilities. - */ - -/* The input buffer contains transparency = 1 - alpha, this converts it to - * alpha. Also clamp since alpha might end up outside of 0..1 due to Russian - * roulette. */ -ccl_device_forceinline float film_transparency_to_alpha(float transparency) -{ - return saturate(1.0f - transparency); -} - -ccl_device_inline float film_get_scale(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer) -{ - if (kfilm_convert->pass_sample_count == PASS_UNUSED) { - return kfilm_convert->scale; - } - - if (kfilm_convert->pass_use_filter) { - const uint sample_count = *( - (ccl_global const uint *)(buffer + kfilm_convert->pass_sample_count)); - return 1.0f / sample_count; - } - - return 1.0f; -} - -ccl_device_inline float film_get_scale_exposure(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer) -{ - if (kfilm_convert->pass_sample_count == PASS_UNUSED) { - return kfilm_convert->scale_exposure; - } - - const float scale = film_get_scale(kfilm_convert, buffer); - - if (kfilm_convert->pass_use_exposure) { - return scale * kfilm_convert->exposure; - } - - return scale; -} - -ccl_device_inline bool film_get_scale_and_scale_exposure( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict scale, - ccl_private float *ccl_restrict scale_exposure) -{ - if (kfilm_convert->pass_sample_count == PASS_UNUSED) { - *scale = kfilm_convert->scale; - *scale_exposure = kfilm_convert->scale_exposure; - return true; - } - - const uint sample_count = *( - (ccl_global const uint *)(buffer + kfilm_convert->pass_sample_count)); - if (!sample_count) { - *scale = 0.0f; - *scale_exposure = 0.0f; - return false; - } - - if (kfilm_convert->pass_use_filter) { - *scale = 1.0f / sample_count; - } - else { - *scale = 1.0f; - } - - if (kfilm_convert->pass_use_exposure) { - *scale_exposure = *scale * kfilm_convert->exposure; - } - else { - *scale_exposure = *scale; - } - - return true; -} - -/* -------------------------------------------------------------------- - * Float (scalar) passes. - */ - -ccl_device_inline void film_get_pass_pixel_depth(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 1); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - const float scale_exposure = film_get_scale_exposure(kfilm_convert, buffer); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - const float f = *in; - - pixel[0] = (f == 0.0f) ? 1e10f : f * scale_exposure; -} - -ccl_device_inline void film_get_pass_pixel_mist(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 1); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - const float scale_exposure = film_get_scale_exposure(kfilm_convert, buffer); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - const float f = *in; - - /* Note that we accumulate 1 - mist in the kernel to avoid having to - * track the mist values in the integrator state. */ - pixel[0] = saturate(1.0f - f * scale_exposure); -} - -ccl_device_inline void film_get_pass_pixel_sample_count( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - /* TODO(sergey): Consider normalizing into the [0..1] range, so that it is possible to see - * meaningful value when adaptive sampler stopped rendering image way before the maximum - * number of samples was reached (for examples when number of samples is set to 0 in - * viewport). */ - - kernel_assert(kfilm_convert->num_components >= 1); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - const float f = *in; - - pixel[0] = __float_as_uint(f) * kfilm_convert->scale; -} - -ccl_device_inline void film_get_pass_pixel_float(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 1); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - const float scale_exposure = film_get_scale_exposure(kfilm_convert, buffer); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - const float f = *in; - - pixel[0] = f * scale_exposure; -} - -/* -------------------------------------------------------------------- - * Float 3 passes. - */ - -ccl_device_inline void film_get_pass_pixel_light_path( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 3); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - /* Read light pass. */ - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - float3 f = make_float3(in[0], in[1], in[2]); - - /* Optionally add indirect light pass. */ - if (kfilm_convert->pass_indirect != PASS_UNUSED) { - ccl_global const float *in_indirect = buffer + kfilm_convert->pass_indirect; - const float3 f_indirect = make_float3(in_indirect[0], in_indirect[1], in_indirect[2]); - f += f_indirect; - } - - /* Optionally divide out color. */ - if (kfilm_convert->pass_divide != PASS_UNUSED) { - ccl_global const float *in_divide = buffer + kfilm_convert->pass_divide; - const float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]); - f = safe_divide_even_color(f, f_divide); - - /* Exposure only, sample scale cancels out. */ - f *= kfilm_convert->exposure; - } - else { - /* Sample scale and exposure. */ - f *= film_get_scale_exposure(kfilm_convert, buffer); - } - - pixel[0] = f.x; - pixel[1] = f.y; - pixel[2] = f.z; -} - -ccl_device_inline void film_get_pass_pixel_float3(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 3); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - const float scale_exposure = film_get_scale_exposure(kfilm_convert, buffer); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - - const float3 f = make_float3(in[0], in[1], in[2]) * scale_exposure; - - pixel[0] = f.x; - pixel[1] = f.y; - pixel[2] = f.z; -} - -/* -------------------------------------------------------------------- - * Float4 passes. - */ - -ccl_device_inline void film_get_pass_pixel_motion(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components == 4); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - kernel_assert(kfilm_convert->pass_motion_weight != PASS_UNUSED); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - ccl_global const float *in_weight = buffer + kfilm_convert->pass_motion_weight; - - const float weight = in_weight[0]; - const float weight_inv = (weight > 0.0f) ? 1.0f / weight : 0.0f; - - const float4 motion = make_float4(in[0], in[1], in[2], in[3]) * weight_inv; - - pixel[0] = motion.x; - pixel[1] = motion.y; - pixel[2] = motion.z; - pixel[3] = motion.w; -} - -ccl_device_inline void film_get_pass_pixel_cryptomatte( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components == 4); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - const float scale = film_get_scale(kfilm_convert, buffer); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - - const float4 f = make_float4(in[0], in[1], in[2], in[3]); - - /* x and z contain integer IDs, don't rescale them. - * y and w contain matte weights, they get scaled. */ - pixel[0] = f.x; - pixel[1] = f.y * scale; - pixel[2] = f.z; - pixel[3] = f.w * scale; -} - -ccl_device_inline void film_get_pass_pixel_float4(ccl_global const KernelFilmConvert *ccl_restrict - kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components == 4); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - float scale, scale_exposure; - film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure); - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - - const float3 color = make_float3(in[0], in[1], in[2]) * scale_exposure; - const float alpha = in[3] * scale; - - pixel[0] = color.x; - pixel[1] = color.y; - pixel[2] = color.z; - pixel[3] = alpha; -} - -ccl_device_inline void film_get_pass_pixel_combined( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components == 4); - - /* 3rd channel contains transparency = 1 - alpha for the combined pass. */ - - kernel_assert(kfilm_convert->num_components == 4); - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - - float scale, scale_exposure; - if (!film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure)) { - pixel[0] = 0.0f; - pixel[1] = 0.0f; - pixel[2] = 0.0f; - pixel[3] = 0.0f; - return; - } - - ccl_global const float *in = buffer + kfilm_convert->pass_offset; - - const float3 color = make_float3(in[0], in[1], in[2]) * scale_exposure; - const float alpha = in[3] * scale; - - pixel[0] = color.x; - pixel[1] = color.y; - pixel[2] = color.z; - pixel[3] = film_transparency_to_alpha(alpha); -} - -/* -------------------------------------------------------------------- - * Shadow catcher. - */ - -ccl_device_inline float3 film_calculate_shadow_catcher_denoised( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer) -{ - kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); - - float 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; - - const float3 pixel = make_float3(in_catcher[0], in_catcher[1], in_catcher[2]) * scale_exposure; - - return pixel; -} - -ccl_device_inline float3 safe_divide_shadow_catcher(float3 a, float3 b) -{ - float x, y, z; - - x = (b.x != 0.0f) ? a.x / b.x : 1.0f; - y = (b.y != 0.0f) ? a.y / b.y : 1.0f; - z = (b.z != 0.0f) ? a.z / b.z : 1.0f; - - return make_float3(x, y, z); -} - -ccl_device_inline float3 -film_calculate_shadow_catcher(ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer) -{ - /* 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 - * to be calculated as division). */ - - if (kfilm_convert->is_denoised) { - return film_calculate_shadow_catcher_denoised(kfilm_convert, buffer); - } - - kernel_assert(kfilm_convert->pass_shadow_catcher_sample_count != PASS_UNUSED); - - /* If there is no shadow catcher object in this pixel, there is no modification of the light - * needed, so return one. */ - ccl_global const float *in_catcher_sample_count = - buffer + kfilm_convert->pass_shadow_catcher_sample_count; - const float num_samples = in_catcher_sample_count[0]; - if (num_samples == 0.0f) { - return one_float3(); - } - - kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); - ccl_global const float *in_catcher = buffer + kfilm_convert->pass_shadow_catcher; - - /* 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 auxiliary passes required - * for the decision (to save up memory). So delay the asserts to this point so that the number of - * samples check handles such configuration. */ - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - kernel_assert(kfilm_convert->pass_combined != PASS_UNUSED); - kernel_assert(kfilm_convert->pass_shadow_catcher_matte != PASS_UNUSED); - - ccl_global const float *in_combined = buffer + kfilm_convert->pass_combined; - ccl_global const float *in_matte = buffer + kfilm_convert->pass_shadow_catcher_matte; - - /* No scaling needed. The integration works in way that number of samples in the combined and - * shadow catcher passes are the same, and exposure is canceled during the division. */ - const float3 color_catcher = make_float3(in_catcher[0], in_catcher[1], in_catcher[2]); - const float3 color_combined = make_float3(in_combined[0], in_combined[1], in_combined[2]); - const float3 color_matte = make_float3(in_matte[0], in_matte[1], in_matte[2]); - - /* Need to ignore contribution of the matte object when doing division (otherwise there will be - * artifacts caused by anti-aliasing). Since combined pass is used for adaptive sampling and need - * to contain matte objects, we subtract matte objects contribution here. This is the same as if - * the matte objects were not accumulated to the combined pass. */ - const float3 combined_no_matte = color_combined - color_matte; - - const float3 shadow_catcher = safe_divide_shadow_catcher(combined_no_matte, color_catcher); - - const float scale = film_get_scale(kfilm_convert, buffer); - const float transparency = in_combined[3] * scale; - const float alpha = film_transparency_to_alpha(transparency); - - /* Alpha-over on white using transparency of the combined pass. This allows to eliminate - * artifacts which are happening on an edge of a shadow catcher when using transparent film. - * Note that we treat shadow catcher as straight alpha here because alpha got canceled out - * during the division. */ - const float3 pixel = (1.0f - alpha) * one_float3() + alpha * shadow_catcher; - - return pixel; -} - -ccl_device_inline float4 film_calculate_shadow_catcher_matte_with_shadow( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer) -{ - /* The approximation of the shadow is 1 - average(shadow_catcher_pass). A better approximation - * is possible. - * - * 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). */ - - kernel_assert(kfilm_convert->pass_offset != PASS_UNUSED); - kernel_assert(kfilm_convert->pass_shadow_catcher != PASS_UNUSED); - kernel_assert(kfilm_convert->pass_shadow_catcher_matte != PASS_UNUSED); - - float scale, scale_exposure; - if (!film_get_scale_and_scale_exposure(kfilm_convert, buffer, &scale, &scale_exposure)) { - return make_float4(0.0f, 0.0f, 0.0f, 0.0f); - } - - ccl_global const float *in_matte = buffer + kfilm_convert->pass_shadow_catcher_matte; - - 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 float transparency = in_matte[3] * scale; - const float alpha = saturate(1.0f - transparency); - - const float alpha_matte = (1.0f - alpha) * (1.0f - average(shadow_catcher)) + alpha; - - if (kfilm_convert->use_approximate_shadow_catcher_background) { - kernel_assert(kfilm_convert->pass_background != PASS_UNUSED); - - ccl_global const float *in_background = buffer + kfilm_convert->pass_background; - const float3 color_background = make_float3( - in_background[0], in_background[1], in_background[2]) * - scale_exposure; - 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(color_matte.x, color_matte.y, color_matte.z, alpha_matte); -} - -ccl_device_inline void film_get_pass_pixel_shadow_catcher( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components >= 3); - - const float3 pixel_value = film_calculate_shadow_catcher(kfilm_convert, buffer); - - pixel[0] = pixel_value.x; - pixel[1] = pixel_value.y; - pixel[2] = pixel_value.z; -} - -ccl_device_inline void film_get_pass_pixel_shadow_catcher_matte_with_shadow( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - kernel_assert(kfilm_convert->num_components == 3 || kfilm_convert->num_components == 4); - - const float4 pixel_value = film_calculate_shadow_catcher_matte_with_shadow(kfilm_convert, - buffer); - - pixel[0] = pixel_value.x; - pixel[1] = pixel_value.y; - pixel[2] = pixel_value.z; - if (kfilm_convert->num_components == 4) { - pixel[3] = pixel_value.w; - } -} - -/* -------------------------------------------------------------------- - * Compositing and overlays. - */ - -ccl_device_inline void film_apply_pass_pixel_overlays_rgba( - ccl_global const KernelFilmConvert *ccl_restrict kfilm_convert, - ccl_global const float *ccl_restrict buffer, - ccl_private float *ccl_restrict pixel) -{ - if (kfilm_convert->show_active_pixels && - kfilm_convert->pass_adaptive_aux_buffer != PASS_UNUSED) { - if (buffer[kfilm_convert->pass_adaptive_aux_buffer + 3] == 0.0f) { - const float3 active_rgb = make_float3(1.0f, 0.0f, 0.0f); - const float3 mix_rgb = interp(make_float3(pixel[0], pixel[1], pixel[2]), active_rgb, 0.5f); - pixel[0] = mix_rgb.x; - pixel[1] = mix_rgb.y; - pixel[2] = mix_rgb.z; - } - } -} - -CCL_NAMESPACE_END |