Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/film/light_passes.h
| /* SPDX-License-Identifier: Apache-2.0 | /* SPDX-License-Identifier: Apache-2.0 | ||||
| * Copyright 2011-2022 Blender Foundation */ | * Copyright 2011-2022 Blender Foundation */ | ||||
| #pragma once | #pragma once | ||||
| #include "kernel/film/adaptive_sampling.h" | #include "kernel/film/adaptive_sampling.h" | ||||
| #include "kernel/film/write.h" | #include "kernel/film/write.h" | ||||
| #include "kernel/integrator/path_automata.h" | |||||
| #include "kernel/integrator/shadow_catcher.h" | #include "kernel/integrator/shadow_catcher.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * BSDF Evaluation | * BSDF Evaluation | ||||
| * | * | ||||
| * BSDF evaluation result, split between diffuse and glossy. This is used to | * BSDF evaluation result, split between diffuse and glossy. This is used to | ||||
| ▲ Show 20 Lines • Show All 268 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| #endif /* __SHADOW_CATCHER__ */ | #endif /* __SHADOW_CATCHER__ */ | ||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * Render passes. | * Render passes. | ||||
| */ | */ | ||||
| ccl_device_inline void film_write_lpe_passes_float(KernelGlobals kg, | |||||
| const int lpe_state, | |||||
| const float transparent, | |||||
| ccl_global float *ccl_restrict buffer) | |||||
| { | |||||
| if (!kernel_data.has_lpes || lpe_state < 0) { | |||||
| return; | |||||
| } | |||||
| uint num_active_lpe_in_state = 0; | |||||
| const int start_aov_offset = path_automata_get_aovs_in_state( | |||||
| kg, lpe_state, &num_active_lpe_in_state); | |||||
| for (int i = 0; i < num_active_lpe_in_state; i++) { | |||||
| const int pass_offset = kernel_data_fetch(light_path_aovs, start_aov_offset + i); | |||||
| film_write_pass_float(buffer + pass_offset + 3, transparent); | |||||
| } | |||||
| } | |||||
| ccl_device_inline void film_write_lpe_passes_float3(KernelGlobals kg, | |||||
| const int lpe_state, | |||||
| const float3 contribution, | |||||
| ccl_global float *ccl_restrict buffer) | |||||
| { | |||||
| if (!kernel_data.has_lpes || lpe_state < 0) { | |||||
| return; | |||||
| } | |||||
| uint num_active_lpe_in_state = 0; | |||||
| const int start_aov_offset = path_automata_get_aovs_in_state( | |||||
| kg, lpe_state, &num_active_lpe_in_state); | |||||
| for (int i = 0; i < num_active_lpe_in_state; i++) { | |||||
| const int pass_offset = kernel_data_fetch(light_path_aovs, start_aov_offset + i); | |||||
| film_write_pass_float3(buffer + pass_offset, contribution); | |||||
| } | |||||
| } | |||||
| ccl_device_inline void film_write_lpe_passes_float4(KernelGlobals kg, | |||||
| const int lpe_state, | |||||
| const float4 contribution, | |||||
| ccl_global float *ccl_restrict buffer) | |||||
| { | |||||
| if (!kernel_data.has_lpes || lpe_state < 0) { | |||||
| return; | |||||
| } | |||||
| uint num_active_lpe_in_state = 0; | |||||
| const int start_aov_offset = path_automata_get_aovs_in_state( | |||||
| kg, lpe_state, &num_active_lpe_in_state); | |||||
| for (int i = 0; i < num_active_lpe_in_state; i++) { | |||||
| const int pass_offset = kernel_data_fetch(light_path_aovs, start_aov_offset + i); | |||||
| // film_write_pass_float4(buffer + pass_offset, contribution); | |||||
| // TODO(lpe): properly handle alpha. | |||||
| film_write_pass_float3(buffer + pass_offset, | |||||
| make_float3(contribution.x, contribution.y, contribution.z)); | |||||
| } | |||||
| } | |||||
| /* Write combined pass. */ | /* Write combined pass. */ | ||||
| ccl_device_inline void film_write_combined_pass(KernelGlobals kg, | ccl_device_inline void film_write_combined_pass(KernelGlobals kg, | ||||
| const int lpe_state, | |||||
| const uint32_t path_flag, | const uint32_t path_flag, | ||||
| const int sample, | const int sample, | ||||
| const Spectrum contribution, | const Spectrum contribution, | ||||
| ccl_global float *ccl_restrict buffer) | ccl_global float *ccl_restrict buffer) | ||||
| { | { | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| if (film_write_shadow_catcher(kg, path_flag, contribution, buffer)) { | if (film_write_shadow_catcher(kg, path_flag, contribution, buffer)) { | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | ||||
| film_write_pass_spectrum(buffer + kernel_data.film.pass_combined, contribution); | film_write_pass_spectrum(buffer + kernel_data.film.pass_combined, contribution); | ||||
| } | } | ||||
| film_write_lpe_passes_float3(kg, lpe_state, contribution, buffer); | |||||
| film_write_adaptive_buffer(kg, sample, contribution, buffer); | film_write_adaptive_buffer(kg, sample, contribution, buffer); | ||||
| } | } | ||||
| /* Write combined pass with transparency. */ | /* Write combined pass with transparency. */ | ||||
| ccl_device_inline void film_write_combined_transparent_pass(KernelGlobals kg, | ccl_device_inline void film_write_combined_transparent_pass(KernelGlobals kg, | ||||
| const int lpe_state, | |||||
| const uint32_t path_flag, | const uint32_t path_flag, | ||||
| const int sample, | const int sample, | ||||
| const Spectrum contribution, | const Spectrum contribution, | ||||
| const float transparent, | const float transparent, | ||||
| ccl_global float *ccl_restrict buffer) | ccl_global float *ccl_restrict buffer) | ||||
| { | { | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| if (film_write_shadow_catcher_transparent(kg, path_flag, contribution, transparent, buffer)) { | if (film_write_shadow_catcher_transparent(kg, path_flag, contribution, transparent, buffer)) { | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | ||||
| const float3 contribution_rgb = spectrum_to_rgb(contribution); | const float3 contribution_rgb = spectrum_to_rgb(contribution); | ||||
| film_write_pass_float4( | film_write_pass_float4( | ||||
| buffer + kernel_data.film.pass_combined, | buffer + kernel_data.film.pass_combined, | ||||
| make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent)); | make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent)); | ||||
| } | } | ||||
| const float4 transparent_contribution = make_float4( | |||||
| contribution.x, contribution.y, contribution.z, transparent); | |||||
| film_write_lpe_passes_float4(kg, lpe_state, transparent_contribution, buffer); | |||||
| film_write_adaptive_buffer(kg, sample, contribution, buffer); | film_write_adaptive_buffer(kg, sample, contribution, buffer); | ||||
| } | } | ||||
| /* Write background or emission to appropriate pass. */ | /* Write background or emission to appropriate pass. */ | ||||
| ccl_device_inline void film_write_emission_or_background_pass( | ccl_device_inline void film_write_emission_or_background_pass( | ||||
| KernelGlobals kg, | KernelGlobals kg, | ||||
| ConstIntegratorState state, | ConstIntegratorState state, | ||||
| Spectrum contribution, | Spectrum contribution, | ||||
| ccl_global float *ccl_restrict buffer, | ccl_global float *ccl_restrict buffer, | ||||
| const int pass, | const int pass, | ||||
| const int lightgroup = LIGHTGROUP_NONE) | const int lightgroup = LIGHTGROUP_NONE) | ||||
| { | { | ||||
| const int lpe_state = INTEGRATOR_STATE(state, path, lpe_state); | |||||
| film_write_lpe_passes_float3(kg, lpe_state, contribution, buffer); | |||||
| if (!(kernel_data.film.light_pass_flag & PASS_ANY)) { | if (!(kernel_data.film.light_pass_flag & PASS_ANY)) { | ||||
| return; | return; | ||||
| } | } | ||||
| #ifdef __PASSES__ | #ifdef __PASSES__ | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| int pass_offset = PASS_UNUSED; | int pass_offset = PASS_UNUSED; | ||||
| /* Denoising albedo. */ | /* Denoising albedo. */ | ||||
| # ifdef __DENOISING_FEATURES__ | # ifdef __DENOISING_FEATURES__ | ||||
| if (path_flag & PATH_RAY_DENOISING_FEATURES) { | if (path_flag & PATH_RAY_DENOISING_FEATURES) { | ||||
| if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | ||||
| const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( | const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( | ||||
| state, path, denoising_feature_throughput); | state, path, denoising_feature_throughput); | ||||
| const Spectrum denoising_albedo = denoising_feature_throughput * contribution; | const Spectrum denoising_albedo = denoising_feature_throughput * contribution; | ||||
| film_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | film_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | ||||
| } | } | ||||
| } | } | ||||
| // TODO(lpe) path_automata_emit_albedo_event(kg, state, -1); | |||||
| # endif /* __DENOISING_FEATURES__ */ | # endif /* __DENOISING_FEATURES__ */ | ||||
| if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { | if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { | ||||
| film_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, | film_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, | ||||
| contribution); | contribution); | ||||
| } | } | ||||
| if (!(path_flag & PATH_RAY_ANY_PASS)) { | if (!(path_flag & PATH_RAY_ANY_PASS)) { | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | ccl_device_inline void film_write_direct_light(KernelGlobals kg, | ||||
| const int sample = INTEGRATOR_STATE(state, shadow_path, sample); | const int sample = INTEGRATOR_STATE(state, shadow_path, sample); | ||||
| /* Ambient occlusion. */ | /* Ambient occlusion. */ | ||||
| if (path_flag & PATH_RAY_SHADOW_FOR_AO) { | if (path_flag & PATH_RAY_SHADOW_FOR_AO) { | ||||
| if ((kernel_data.kernel_features & KERNEL_FEATURE_AO_PASS) && (path_flag & PATH_RAY_CAMERA)) { | if ((kernel_data.kernel_features & KERNEL_FEATURE_AO_PASS) && (path_flag & PATH_RAY_CAMERA)) { | ||||
| film_write_pass_spectrum(buffer + kernel_data.film.pass_ao, contribution); | film_write_pass_spectrum(buffer + kernel_data.film.pass_ao, contribution); | ||||
| } | } | ||||
| if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) { | if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) { | ||||
| const int lpe_state = INTEGRATOR_STATE(state, shadow_path, lpe_state); | |||||
| const Spectrum ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput); | const Spectrum ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput); | ||||
| film_write_combined_pass(kg, path_flag, sample, contribution * ao_weight, buffer); | film_write_combined_pass(kg, lpe_state, path_flag, sample, contribution * ao_weight, buffer); | ||||
| } | } | ||||
| return; | return; | ||||
| } | } | ||||
| /* Direct light shadow. */ | /* Direct light shadow. */ | ||||
| film_write_combined_pass(kg, path_flag, sample, contribution, buffer); | const int lpe_state = INTEGRATOR_STATE(state, shadow_path, lpe_state); | ||||
| film_write_combined_pass(kg, lpe_state, path_flag, sample, contribution, buffer); | |||||
| #ifdef __PASSES__ | #ifdef __PASSES__ | ||||
| if (kernel_data.film.light_pass_flag & PASS_ANY) { | if (kernel_data.film.light_pass_flag & PASS_ANY) { | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag); | ||||
| /* Don't write any light passes for shadow catcher, for easier | /* Don't write any light passes for shadow catcher, for easier | ||||
| * compositing back together of the combined pass. */ | * compositing back together of the combined pass. */ | ||||
| if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) { | if (path_flag & PATH_RAY_SHADOW_CATCHER_HIT) { | ||||
| ▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | ccl_device_inline void film_write_transparent(KernelGlobals kg, | ||||
| const uint32_t path_flag, | const uint32_t path_flag, | ||||
| const float transparent, | const float transparent, | ||||
| ccl_global float *ccl_restrict buffer) | ccl_global float *ccl_restrict buffer) | ||||
| { | { | ||||
| if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { | ||||
| film_write_pass_float(buffer + kernel_data.film.pass_combined + 3, transparent); | film_write_pass_float(buffer + kernel_data.film.pass_combined + 3, transparent); | ||||
| } | } | ||||
| const int lpe_state = INTEGRATOR_STATE(state, path, lpe_state); | |||||
| film_write_lpe_passes_float(kg, lpe_state, transparent, buffer); | |||||
| film_write_shadow_catcher_transparent_only(kg, path_flag, transparent, buffer); | film_write_shadow_catcher_transparent_only(kg, path_flag, transparent, buffer); | ||||
| } | } | ||||
| /* Write holdout to render buffer. */ | /* Write holdout to render buffer. */ | ||||
| ccl_device_inline void film_write_holdout(KernelGlobals kg, | ccl_device_inline void film_write_holdout(KernelGlobals kg, | ||||
| ConstIntegratorState state, | ConstIntegratorState state, | ||||
| const uint32_t path_flag, | const uint32_t path_flag, | ||||
| const float transparent, | const float transparent, | ||||
| Show All 19 Lines | ccl_device_inline void film_write_background(KernelGlobals kg, | ||||
| ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| if (is_transparent_background_ray) { | if (is_transparent_background_ray) { | ||||
| film_write_transparent(kg, state, path_flag, transparent, buffer); | film_write_transparent(kg, state, path_flag, transparent, buffer); | ||||
| } | } | ||||
| else { | else { | ||||
| const int sample = INTEGRATOR_STATE(state, path, sample); | const int sample = INTEGRATOR_STATE(state, path, sample); | ||||
| film_write_combined_transparent_pass(kg, path_flag, sample, contribution, transparent, buffer); | const int lpe_state = INTEGRATOR_STATE(state, path, lpe_state); | ||||
| film_write_combined_transparent_pass( | |||||
| kg, lpe_state, path_flag, sample, contribution, transparent, buffer); | |||||
| } | } | ||||
| film_write_emission_or_background_pass(kg, | film_write_emission_or_background_pass(kg, | ||||
| state, | state, | ||||
| contribution, | contribution, | ||||
| buffer, | buffer, | ||||
| kernel_data.film.pass_background, | kernel_data.film.pass_background, | ||||
| kernel_data.background.lightgroup); | kernel_data.background.lightgroup); | ||||
| } | } | ||||
| /* Write emission to render buffer. */ | /* Write emission to render buffer. */ | ||||
| ccl_device_inline void film_write_volume_emission(KernelGlobals kg, | ccl_device_inline void film_write_volume_emission(KernelGlobals kg, | ||||
| ConstIntegratorState state, | ConstIntegratorState state, | ||||
| const Spectrum L, | const Spectrum L, | ||||
| ccl_global float *ccl_restrict render_buffer, | ccl_global float *ccl_restrict render_buffer, | ||||
| const int lightgroup = LIGHTGROUP_NONE) | const int lightgroup = LIGHTGROUP_NONE) | ||||
| { | { | ||||
| Spectrum contribution = L; | Spectrum contribution = L; | ||||
| film_clamp_light(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); | film_clamp_light(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); | ||||
| ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| const int sample = INTEGRATOR_STATE(state, path, sample); | const int sample = INTEGRATOR_STATE(state, path, sample); | ||||
| const int lpe_state = INTEGRATOR_STATE(state, path, lpe_state); | |||||
| film_write_combined_pass(kg, path_flag, sample, contribution, buffer); | film_write_combined_pass(kg, lpe_state, path_flag, sample, contribution, buffer); | ||||
| film_write_emission_or_background_pass( | film_write_emission_or_background_pass( | ||||
| kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup); | kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup); | ||||
| } | } | ||||
| ccl_device_inline void film_write_surface_emission(KernelGlobals kg, | ccl_device_inline void film_write_surface_emission(KernelGlobals kg, | ||||
| ConstIntegratorState state, | ConstIntegratorState state, | ||||
| const Spectrum L, | const Spectrum L, | ||||
| const float mis_weight, | const float mis_weight, | ||||
| ccl_global float *ccl_restrict render_buffer, | ccl_global float *ccl_restrict render_buffer, | ||||
| const int lightgroup = LIGHTGROUP_NONE) | const int lightgroup = LIGHTGROUP_NONE) | ||||
| { | { | ||||
| Spectrum contribution = INTEGRATOR_STATE(state, path, throughput) * L * mis_weight; | Spectrum contribution = INTEGRATOR_STATE(state, path, throughput) * L * mis_weight; | ||||
| film_clamp_light(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); | film_clamp_light(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); | ||||
| ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| const int sample = INTEGRATOR_STATE(state, path, sample); | const int sample = INTEGRATOR_STATE(state, path, sample); | ||||
| const int lpe_state = INTEGRATOR_STATE(state, path, lpe_state); | |||||
| film_write_combined_pass(kg, path_flag, sample, contribution, buffer); | film_write_combined_pass(kg, lpe_state, path_flag, sample, contribution, buffer); | ||||
| film_write_emission_or_background_pass( | film_write_emission_or_background_pass( | ||||
| kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup); | kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup); | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||