Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_passes.h
| Show All 19 Lines | |||||
| #include "kernel/kernel_id_passes.h" | #include "kernel/kernel_id_passes.h" | ||||
| #include "kernel/kernel_write_passes.h" | #include "kernel/kernel_write_passes.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* Get pointer to pixel in render buffer. */ | /* Get pointer to pixel in render buffer. */ | ||||
| ccl_device_forceinline ccl_global float *kernel_pass_pixel_render_buffer( | ccl_device_forceinline ccl_global float *kernel_pass_pixel_render_buffer( | ||||
| INTEGRATOR_STATE_CONST_ARGS, ccl_global float *ccl_restrict render_buffer) | KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer) | ||||
| { | { | ||||
| const uint32_t render_pixel_index = INTEGRATOR_STATE(path, render_pixel_index); | const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index); | ||||
| const uint64_t render_buffer_offset = (uint64_t)render_pixel_index * | const uint64_t render_buffer_offset = (uint64_t)render_pixel_index * | ||||
| kernel_data.film.pass_stride; | kernel_data.film.pass_stride; | ||||
| return render_buffer + render_buffer_offset; | return render_buffer + render_buffer_offset; | ||||
| } | } | ||||
| #ifdef __DENOISING_FEATURES__ | #ifdef __DENOISING_FEATURES__ | ||||
| ccl_device_forceinline void kernel_write_denoising_features_surface( | ccl_device_forceinline void kernel_write_denoising_features_surface( | ||||
| INTEGRATOR_STATE_ARGS, | KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_global float *ccl_restrict render_buffer) | ccl_global float *ccl_restrict render_buffer) | ||||
| { | { | ||||
| if (!(INTEGRATOR_STATE(path, flag) & PATH_RAY_DENOISING_FEATURES)) { | if (!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_DENOISING_FEATURES)) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Skip implicitly transparent surfaces. */ | /* Skip implicitly transparent surfaces. */ | ||||
| if (sd->flag & SD_HAS_ONLY_VOLUME) { | if (sd->flag & SD_HAS_ONLY_VOLUME) { | ||||
| return; | return; | ||||
| } | } | ||||
| ccl_global float *buffer = kernel_pass_pixel_render_buffer(INTEGRATOR_STATE_PASS, render_buffer); | ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| float3 normal = zero_float3(); | float3 normal = zero_float3(); | ||||
| float3 diffuse_albedo = zero_float3(); | float3 diffuse_albedo = zero_float3(); | ||||
| float3 specular_albedo = zero_float3(); | float3 specular_albedo = zero_float3(); | ||||
| float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f; | float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f; | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (kernel_data.film.pass_denoising_normal != PASS_UNUSED) { | ||||
| const Transform worldtocamera = kernel_data.cam.worldtocamera; | const Transform worldtocamera = kernel_data.cam.worldtocamera; | ||||
| normal = transform_direction(&worldtocamera, normal); | normal = transform_direction(&worldtocamera, normal); | ||||
| const float3 denoising_normal = ensure_finite3(normal); | const float3 denoising_normal = ensure_finite3(normal); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal); | kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal); | ||||
| } | } | ||||
| if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | ||||
| const float3 denoising_feature_throughput = INTEGRATOR_STATE(path, | const float3 denoising_feature_throughput = INTEGRATOR_STATE( | ||||
| denoising_feature_throughput); | state, path, denoising_feature_throughput); | ||||
| const float3 denoising_albedo = ensure_finite3(denoising_feature_throughput * | const float3 denoising_albedo = ensure_finite3(denoising_feature_throughput * | ||||
| diffuse_albedo); | diffuse_albedo); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | ||||
| } | } | ||||
| INTEGRATOR_STATE_WRITE(path, flag) &= ~PATH_RAY_DENOISING_FEATURES; | INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES; | ||||
| } | } | ||||
| else { | else { | ||||
| INTEGRATOR_STATE_WRITE(path, denoising_feature_throughput) *= specular_albedo; | INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) *= specular_albedo; | ||||
| } | } | ||||
| } | } | ||||
| ccl_device_forceinline void kernel_write_denoising_features_volume(INTEGRATOR_STATE_ARGS, | ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| const float3 albedo, | const float3 albedo, | ||||
| const bool scatter, | const bool scatter, | ||||
| ccl_global float *ccl_restrict | ccl_global float *ccl_restrict | ||||
| render_buffer) | render_buffer) | ||||
| { | { | ||||
| ccl_global float *buffer = kernel_pass_pixel_render_buffer(INTEGRATOR_STATE_PASS, render_buffer); | ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| const float3 denoising_feature_throughput = INTEGRATOR_STATE(path, denoising_feature_throughput); | const float3 denoising_feature_throughput = INTEGRATOR_STATE( | ||||
| state, path, denoising_feature_throughput); | |||||
| if (scatter && kernel_data.film.pass_denoising_normal != PASS_UNUSED) { | if (scatter && kernel_data.film.pass_denoising_normal != PASS_UNUSED) { | ||||
| /* Assume scatter is sufficiently diffuse to stop writing denoising features. */ | /* Assume scatter is sufficiently diffuse to stop writing denoising features. */ | ||||
| INTEGRATOR_STATE_WRITE(path, flag) &= ~PATH_RAY_DENOISING_FEATURES; | INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES; | ||||
| /* Write view direction as normal. */ | /* Write view direction as normal. */ | ||||
| const float3 denoising_normal = make_float3(0.0f, 0.0f, -1.0f); | const float3 denoising_normal = make_float3(0.0f, 0.0f, -1.0f); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal); | kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal); | ||||
| } | } | ||||
| if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { | ||||
| /* Write albedo. */ | /* Write albedo. */ | ||||
| const float3 denoising_albedo = ensure_finite3(denoising_feature_throughput * albedo); | const float3 denoising_albedo = ensure_finite3(denoising_feature_throughput * albedo); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __DENOISING_FEATURES__ */ | #endif /* __DENOISING_FEATURES__ */ | ||||
| #ifdef __SHADOW_CATCHER__ | #ifdef __SHADOW_CATCHER__ | ||||
| /* Write shadow catcher passes on a bounce from the shadow catcher object. */ | /* Write shadow catcher passes on a bounce from the shadow catcher object. */ | ||||
| ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data( | ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data( | ||||
| INTEGRATOR_STATE_ARGS, | KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_global float *ccl_restrict render_buffer) | ccl_global float *ccl_restrict render_buffer) | ||||
| { | { | ||||
| if (!kernel_data.integrator.has_shadow_catcher) { | if (!kernel_data.integrator.has_shadow_catcher) { | ||||
| return; | return; | ||||
| } | } | ||||
| kernel_assert(kernel_data.film.pass_shadow_catcher_sample_count != PASS_UNUSED); | kernel_assert(kernel_data.film.pass_shadow_catcher_sample_count != PASS_UNUSED); | ||||
| kernel_assert(kernel_data.film.pass_shadow_catcher_matte != PASS_UNUSED); | kernel_assert(kernel_data.film.pass_shadow_catcher_matte != PASS_UNUSED); | ||||
| if (!kernel_shadow_catcher_is_path_split_bounce(INTEGRATOR_STATE_PASS, sd->object_flag)) { | if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, sd->object_flag)) { | ||||
| return; | return; | ||||
| } | } | ||||
| ccl_global float *buffer = kernel_pass_pixel_render_buffer(INTEGRATOR_STATE_PASS, render_buffer); | ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| /* Count sample for the shadow catcher object. */ | /* Count sample for the shadow catcher object. */ | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_sample_count, 1.0f); | kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_sample_count, 1.0f); | ||||
| /* Since the split is done, the sample does not contribute to the matte, so accumulate it as | /* Since the split is done, the sample does not contribute to the matte, so accumulate it as | ||||
| * transparency to the matte. */ | * transparency to the matte. */ | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3, | kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3, | ||||
| average(throughput)); | average(throughput)); | ||||
| } | } | ||||
| #endif /* __SHADOW_CATCHER__ */ | #endif /* __SHADOW_CATCHER__ */ | ||||
| ccl_device_inline size_t kernel_write_id_pass(ccl_global float *ccl_restrict buffer, | ccl_device_inline size_t kernel_write_id_pass(ccl_global float *ccl_restrict buffer, | ||||
| size_t depth, | size_t depth, | ||||
| float id, | float id, | ||||
| float matte_weight) | float matte_weight) | ||||
| { | { | ||||
| kernel_write_id_slots(buffer, depth * 2, id, matte_weight); | kernel_write_id_slots(buffer, depth * 2, id, matte_weight); | ||||
| return depth * 4; | return depth * 4; | ||||
| } | } | ||||
| ccl_device_inline void kernel_write_data_passes(INTEGRATOR_STATE_ARGS, | ccl_device_inline void kernel_write_data_passes(KernelGlobals kg, | ||||
| IntegratorState state, | |||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_global float *ccl_restrict render_buffer) | ccl_global float *ccl_restrict render_buffer) | ||||
| { | { | ||||
| #ifdef __PASSES__ | #ifdef __PASSES__ | ||||
| const int path_flag = INTEGRATOR_STATE(path, flag); | const int path_flag = INTEGRATOR_STATE(state, path, flag); | ||||
| if (!(path_flag & PATH_RAY_CAMERA)) { | if (!(path_flag & PATH_RAY_CAMERA)) { | ||||
| return; | return; | ||||
| } | } | ||||
| const int flag = kernel_data.film.pass_flag; | const int flag = kernel_data.film.pass_flag; | ||||
| if (!(flag & PASS_ANY)) { | if (!(flag & PASS_ANY)) { | ||||
| return; | return; | ||||
| } | } | ||||
| ccl_global float *buffer = kernel_pass_pixel_render_buffer(INTEGRATOR_STATE_PASS, render_buffer); | ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); | ||||
| if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) { | if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) { | ||||
| if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f || | if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f || | ||||
| average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { | average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { | ||||
| if (INTEGRATOR_STATE(path, sample) == 0) { | if (INTEGRATOR_STATE(state, path, sample) == 0) { | ||||
| if (flag & PASSMASK(DEPTH)) { | if (flag & PASSMASK(DEPTH)) { | ||||
| const float depth = camera_z_depth(kg, sd->P); | const float depth = camera_z_depth(kg, sd->P); | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth); | kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth); | ||||
| } | } | ||||
| if (flag & PASSMASK(OBJECT_ID)) { | if (flag & PASSMASK(OBJECT_ID)) { | ||||
| const float id = object_pass_id(kg, sd->object); | const float id = object_pass_id(kg, sd->object); | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id); | kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id); | ||||
| } | } | ||||
| Show All 20 Lines | if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f || | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv); | kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv); | ||||
| } | } | ||||
| if (flag & PASSMASK(MOTION)) { | if (flag & PASSMASK(MOTION)) { | ||||
| const float4 speed = primitive_motion_vector(kg, sd); | const float4 speed = primitive_motion_vector(kg, sd); | ||||
| kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed); | kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed); | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f); | kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f); | ||||
| } | } | ||||
| INTEGRATOR_STATE_WRITE(path, flag) |= PATH_RAY_SINGLE_PASS_DONE; | INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SINGLE_PASS_DONE; | ||||
| } | } | ||||
| } | } | ||||
| if (kernel_data.film.cryptomatte_passes) { | if (kernel_data.film.cryptomatte_passes) { | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| const float matte_weight = average(throughput) * | const float matte_weight = average(throughput) * | ||||
| (1.0f - average(shader_bsdf_transparency(kg, sd))); | (1.0f - average(shader_bsdf_transparency(kg, sd))); | ||||
| if (matte_weight > 0.0f) { | if (matte_weight > 0.0f) { | ||||
| ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte; | ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte; | ||||
| if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) { | if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) { | ||||
| const float id = object_cryptomatte_id(kg, sd->object); | const float id = object_cryptomatte_id(kg, sd->object); | ||||
| cryptomatte_buffer += kernel_write_id_pass( | cryptomatte_buffer += kernel_write_id_pass( | ||||
| cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | ||||
| } | } | ||||
| if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) { | if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) { | ||||
| const float id = shader_cryptomatte_id(kg, sd->shader); | const float id = shader_cryptomatte_id(kg, sd->shader); | ||||
| cryptomatte_buffer += kernel_write_id_pass( | cryptomatte_buffer += kernel_write_id_pass( | ||||
| cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | ||||
| } | } | ||||
| if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) { | if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) { | ||||
| const float id = object_cryptomatte_asset_id(kg, sd->object); | const float id = object_cryptomatte_asset_id(kg, sd->object); | ||||
| cryptomatte_buffer += kernel_write_id_pass( | cryptomatte_buffer += kernel_write_id_pass( | ||||
| cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (flag & PASSMASK(DIFFUSE_COLOR)) { | if (flag & PASSMASK(DIFFUSE_COLOR)) { | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, | kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, | ||||
| shader_bsdf_diffuse(kg, sd) * throughput); | shader_bsdf_diffuse(kg, sd) * throughput); | ||||
| } | } | ||||
| if (flag & PASSMASK(GLOSSY_COLOR)) { | if (flag & PASSMASK(GLOSSY_COLOR)) { | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, | kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, | ||||
| shader_bsdf_glossy(kg, sd) * throughput); | shader_bsdf_glossy(kg, sd) * throughput); | ||||
| } | } | ||||
| if (flag & PASSMASK(TRANSMISSION_COLOR)) { | if (flag & PASSMASK(TRANSMISSION_COLOR)) { | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, | kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, | ||||
| shader_bsdf_transmission(kg, sd) * throughput); | shader_bsdf_transmission(kg, sd) * throughput); | ||||
| } | } | ||||
| if (flag & PASSMASK(MIST)) { | if (flag & PASSMASK(MIST)) { | ||||
| /* Bring depth into 0..1 range. */ | /* Bring depth into 0..1 range. */ | ||||
| const float mist_start = kernel_data.film.mist_start; | const float mist_start = kernel_data.film.mist_start; | ||||
| const float mist_inv_depth = kernel_data.film.mist_inv_depth; | const float mist_inv_depth = kernel_data.film.mist_inv_depth; | ||||
| const float depth = camera_distance(kg, sd->P); | const float depth = camera_distance(kg, sd->P); | ||||
| float mist = saturate((depth - mist_start) * mist_inv_depth); | float mist = saturate((depth - mist_start) * mist_inv_depth); | ||||
| /* Falloff */ | /* Falloff */ | ||||
| const float mist_falloff = kernel_data.film.mist_falloff; | const float mist_falloff = kernel_data.film.mist_falloff; | ||||
| if (mist_falloff == 1.0f) | if (mist_falloff == 1.0f) | ||||
| ; | ; | ||||
| else if (mist_falloff == 2.0f) | else if (mist_falloff == 2.0f) | ||||
| mist = mist * mist; | mist = mist * mist; | ||||
| else if (mist_falloff == 0.5f) | else if (mist_falloff == 0.5f) | ||||
| mist = sqrtf(mist); | mist = sqrtf(mist); | ||||
| else | else | ||||
| mist = powf(mist, mist_falloff); | mist = powf(mist, mist_falloff); | ||||
| /* Modulate by transparency */ | /* Modulate by transparency */ | ||||
| const float3 throughput = INTEGRATOR_STATE(path, throughput); | const float3 throughput = INTEGRATOR_STATE(state, path, throughput); | ||||
| const float3 alpha = shader_bsdf_alpha(kg, sd); | const float3 alpha = shader_bsdf_alpha(kg, sd); | ||||
| const float mist_output = (1.0f - mist) * average(throughput * alpha); | const float mist_output = (1.0f - mist) * average(throughput * alpha); | ||||
| /* Note that the final value in the render buffer we want is 1 - mist_output, | /* Note that the final value in the render buffer we want is 1 - mist_output, | ||||
| * to avoid having to tracking this in the Integrator state we do the negation | * to avoid having to tracking this in the Integrator state we do the negation | ||||
| * after rendering. */ | * after rendering. */ | ||||
| kernel_write_pass_float(buffer + kernel_data.film.pass_mist, mist_output); | kernel_write_pass_float(buffer + kernel_data.film.pass_mist, mist_output); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||