From dcae48d1d395514e23d515685ad68ee7ebfa83f7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 25 Jul 2025 18:09:38 +0200 Subject: [PATCH] Cycles: Add Portal Depth light pass information It allows to implement tricks based on a knowledge whether the path ever cam through a portal or not, and even something more advanced based on the number of portals. The main current objective is for strokes shading: stroke shader uses Ray Portal BSDF to place ray to the center of the stroke and point it in the direction of the surface it is generated for. This gives stroke a single color which matches shading of the original object. For this usecase to work the ray bounced from the original surface should ignore the strokes, which is now possible by using Portal Depth input and mixing with the Transparent BSDF. It also helps to make shading look better when there are multiple stroke layers. A solution of using portal depth is chosen over a single flag due to various factors: - Last time we've looked into it it was a bit tricky to implement as a flag due to us running out of bits. - It feels to be more flexible solution, even though it is a bit hard to come up with 100% compelling setup for it. - It needs to be slightly different from the current "Is Foo" flags, and be more "Is Portal Descendant" or something. An extra uint16 is added to the state to count the portal depth, but it is only allocated for scenes that use Ray Portal BSDF. Portal BSDF still increments Transparent bounce, as it is required to have some "limiting" factor so that ray does not get infinitely move to different place of the scene. Ref #125213 Pull Request: https://projects.blender.org/blender/blender/pulls/143107 --- intern/cycles/kernel/integrator/path_state.h | 5 ++ .../cycles/kernel/integrator/shade_surface.h | 6 ++- .../kernel/integrator/shadow_state_template.h | 2 + .../cycles/kernel/integrator/state_template.h | 2 + intern/cycles/kernel/integrator/state_util.h | 31 +++++++++++ intern/cycles/kernel/osl/services.cpp | 6 +++ intern/cycles/kernel/osl/services.h | 1 + intern/cycles/kernel/osl/services_gpu.h | 7 +++ .../kernel/osl/shaders/node_light_path.osl | 7 ++- intern/cycles/kernel/svm/light_path.h | 9 +++- intern/cycles/kernel/svm/svm.h | 2 +- intern/cycles/kernel/svm/types.h | 2 + intern/cycles/kernel/types.h | 54 ++++++++++--------- intern/cycles/scene/scene.cpp | 1 + intern/cycles/scene/shader_graph.h | 2 +- intern/cycles/scene/shader_nodes.cpp | 6 +++ intern/cycles/scene/shader_nodes.h | 29 +++++----- intern/cycles/scene/svm.cpp | 2 +- scripts/startup/bl_ui/node_add_menu_shader.py | 3 +- .../gpu_shader_material_light_path.glsl | 4 +- .../shader/nodes/node_shader_light_path.cc | 1 + .../light_path_portal_depth.png | 3 ++ .../eevee_renders/light_path_portal_depth.png | 3 ++ .../integrator/light_path_portal_depth.blend | 3 ++ .../light_path_portal_depth.png | 3 ++ .../light_path_portal_depth.png | 3 ++ .../light_path_portal_depth.png | 3 ++ 27 files changed, 155 insertions(+), 45 deletions(-) create mode 100644 tests/files/render/integrator/cycles_renders/light_path_portal_depth.png create mode 100644 tests/files/render/integrator/eevee_renders/light_path_portal_depth.png create mode 100644 tests/files/render/integrator/light_path_portal_depth.blend create mode 100644 tests/files/render/integrator/storm_hydra_renders/light_path_portal_depth.png create mode 100644 tests/files/render/integrator/storm_usd_renders/light_path_portal_depth.png create mode 100644 tests/files/render/integrator/workbench_renders/light_path_portal_depth.png diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h index 101670a9c34..7030f67822e 100644 --- a/intern/cycles/kernel/integrator/path_state.h +++ b/intern/cycles/kernel/integrator/path_state.h @@ -51,6 +51,9 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, INTEGRATOR_STATE_WRITE(state, path, transparent_bounce) = 0; INTEGRATOR_STATE_WRITE(state, path, volume_bounce) = 0; INTEGRATOR_STATE_WRITE(state, path, volume_bounds_bounce) = 0; + if ((kernel_data.kernel_features & KERNEL_FEATURE_NODE_PORTAL)) { + INTEGRATOR_STATE_WRITE(state, path, portal_bounce) = 0; + } INTEGRATOR_STATE_WRITE(state, path, rng_pixel) = rng_pixel; INTEGRATOR_STATE_WRITE(state, path, rng_offset) = PRNG_BOUNCE_NUM; INTEGRATOR_STATE_WRITE(state, path, flag) = PATH_RAY_CAMERA | PATH_RAY_MIS_SKIP | @@ -123,6 +126,8 @@ ccl_device_inline void path_state_next(KernelGlobals kg, if (shader_flag & SD_RAY_PORTAL) { flag |= PATH_RAY_MIS_SKIP; + INTEGRATOR_STATE_WRITE( + state, path, portal_bounce) = INTEGRATOR_STATE(state, path, portal_bounce) + 1; } INTEGRATOR_STATE_WRITE(state, path, flag) = flag; diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index ececa9352e5..942de4cbb35 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -243,9 +243,13 @@ integrate_direct_light_shadow_init_common(KernelGlobals kg, state, path, volume_bounds_bounce); INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, glossy_bounce) = INTEGRATOR_STATE( state, path, glossy_bounce); - INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, throughput) = throughput; + if ((kernel_data.kernel_features & KERNEL_FEATURE_NODE_PORTAL)) { + INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, portal_bounce) = INTEGRATOR_STATE( + state, path, portal_bounce); + } + #ifdef __MNEE__ if (mnee_vertex_count > 0) { INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transmission_bounce) = diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h index a176682b0d4..26118c174f6 100644 --- a/intern/cycles/kernel/integrator/shadow_state_template.h +++ b/intern/cycles/kernel/integrator/shadow_state_template.h @@ -25,6 +25,8 @@ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, glossy_bounce, KERNEL_FEATURE_PATH_T KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, transmission_bounce, KERNEL_FEATURE_PATH_TRACING) /* Current volume bounds ray bounce depth. */ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, volume_bounds_bounce, KERNEL_FEATURE_PATH_TRACING) +/* Current portal ray bounce depth. */ +KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, portal_bounce, KERNEL_FEATURE_NODE_PORTAL) /* DeviceKernel bit indicating queued kernels. */ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, queued_kernel, KERNEL_FEATURE_PATH_TRACING) /* enum PathRayFlag */ diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h index 587c3f8d938..fbbeaaadcc9 100644 --- a/intern/cycles/kernel/integrator/state_template.h +++ b/intern/cycles/kernel/integrator/state_template.h @@ -27,6 +27,8 @@ KERNEL_STRUCT_MEMBER(path, uint16_t, transmission_bounce, KERNEL_FEATURE_PATH_TR KERNEL_STRUCT_MEMBER(path, uint16_t, volume_bounce, KERNEL_FEATURE_PATH_TRACING) /* Current volume bounds ray bounce depth. */ KERNEL_STRUCT_MEMBER(path, uint16_t, volume_bounds_bounce, KERNEL_FEATURE_PATH_TRACING) +/* Current portal ray bounce depth. */ +KERNEL_STRUCT_MEMBER(path, uint16_t, portal_bounce, KERNEL_FEATURE_NODE_PORTAL) /* DeviceKernel bit indicating queued kernels. */ KERNEL_STRUCT_MEMBER(path, uint16_t, queued_kernel, KERNEL_FEATURE_PATH_TRACING) /* Random number generator per-pixel info. */ diff --git a/intern/cycles/kernel/integrator/state_util.h b/intern/cycles/kernel/integrator/state_util.h index 649412881cf..bd222c5ef37 100644 --- a/intern/cycles/kernel/integrator/state_util.h +++ b/intern/cycles/kernel/integrator/state_util.h @@ -530,6 +530,25 @@ ccl_device_inline int integrator_state_transparent_bounce(ConstIntegratorShadowS { return INTEGRATOR_STATE(state, shadow_path, transparent_bounce); } + +ccl_device_inline int integrator_state_portal_bounce(KernelGlobals kg, + ConstIntegratorState state, + const int /*unused*/) +{ + return (kernel_data.kernel_features & KERNEL_FEATURE_NODE_PORTAL) ? + INTEGRATOR_STATE(state, path, portal_bounce) : + 0; +} + +ccl_device_inline int integrator_state_portal_bounce(KernelGlobals kg, + ConstIntegratorShadowState state, + const int /*unused*/) +{ + return (kernel_data.kernel_features & KERNEL_FEATURE_NODE_PORTAL) ? + INTEGRATOR_STATE(state, shadow_path, portal_bounce) : + 0; +} + #else ccl_device_inline int integrator_state_bounce(ConstIntegratorShadowState state, const uint32_t path_flag) @@ -566,6 +585,18 @@ ccl_device_inline int integrator_state_transparent_bounce(ConstIntegratorShadowS return (path_flag & PATH_RAY_SHADOW) ? INTEGRATOR_STATE(state, shadow_path, transparent_bounce) : INTEGRATOR_STATE(state, path, transparent_bounce); } + +ccl_device_inline int integrator_state_portal_bounce(KernelGlobals kg, + ConstIntegratorShadowState state, + const uint32_t path_flag) +{ + if ((kernel_data.kernel_features & KERNEL_FEATURE_NODE_PORTAL) == 0) { + return 0; + } + return (path_flag & PATH_RAY_SHADOW) ? INTEGRATOR_STATE(state, shadow_path, portal_bounce) : + INTEGRATOR_STATE(state, path, portal_bounce); +} + #endif CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index ef40ee72cad..9e936c88c8a 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -106,6 +106,7 @@ ustring OSLRenderServices::u_path_diffuse_depth("path:diffuse_depth"); ustring OSLRenderServices::u_path_glossy_depth("path:glossy_depth"); ustring OSLRenderServices::u_path_transparent_depth("path:transparent_depth"); ustring OSLRenderServices::u_path_transmission_depth("path:transmission_depth"); +ustring OSLRenderServices::u_path_portal_depth("path:portal_depth"); ustring OSLRenderServices::u_trace("trace"); ustring OSLRenderServices::u_hit("hit"); ustring OSLRenderServices::u_hitdist("hitdist"); @@ -926,6 +927,11 @@ bool OSLRenderServices::get_background_attribute( const int f = READ_PATH_STATE(transparent_bounce); return set_attribute(f, type, derivatives, val); } + if (name == u_path_portal_depth) { + /* Portal Ray Depth */ + const int f = READ_PATH_STATE(portal_bounce); + return set_attribute(f, type, derivatives, val); + } #undef READ_PATH_STATE if (name == u_ndc) { diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h index afae34716a4..9ff545dcddc 100644 --- a/intern/cycles/kernel/osl/services.h +++ b/intern/cycles/kernel/osl/services.h @@ -309,6 +309,7 @@ class OSLRenderServices : public OSL::RendererServices { static ustring u_path_glossy_depth; static ustring u_path_transparent_depth; static ustring u_path_transmission_depth; + static ustring u_path_portal_depth; static ustring u_trace; static ustring u_hit; static ustring u_hitdist; diff --git a/intern/cycles/kernel/osl/services_gpu.h b/intern/cycles/kernel/osl/services_gpu.h index df5cf278a67..9a210aad257 100644 --- a/intern/cycles/kernel/osl/services_gpu.h +++ b/intern/cycles/kernel/osl/services_gpu.h @@ -129,6 +129,8 @@ ccl_device_constant DeviceString u_path_glossy_depth = 15717768399057252940ull; ccl_device_constant DeviceString u_path_transparent_depth = 7821650266475578543ull; /* "path:transmission_depth" */ ccl_device_constant DeviceString u_path_transmission_depth = 15113408892323917624ull; +/* "path:portal_depth" */ +ccl_device_constant DeviceString u_path_portal_depth = 13191651286699118408ull; /* "cam:sensor_size" */ ccl_device_constant DeviceString u_sensor_size = 7525693591727141378ull; /* "cam:image_resolution" */ @@ -719,6 +721,11 @@ ccl_device_inline bool get_background_attribute(KernelGlobals kg, const int f = READ_PATH_STATE(transparent_bounce); return set_attribute(f, type, derivatives, val); } + if (name == DeviceStrings::u_path_portal_depth) { + /* Portal Ray Depth */ + const int f = READ_PATH_STATE(portal_bounce); + return set_attribute(f, type, derivatives, val); + } #undef READ_PATH_STATE else if (name == DeviceStrings::u_ndc) { diff --git a/intern/cycles/kernel/osl/shaders/node_light_path.osl b/intern/cycles/kernel/osl/shaders/node_light_path.osl index 1a59cd562fc..475fc6a4ca8 100644 --- a/intern/cycles/kernel/osl/shaders/node_light_path.osl +++ b/intern/cycles/kernel/osl/shaders/node_light_path.osl @@ -17,7 +17,8 @@ shader node_light_path(output float IsCameraRay = 0.0, output float DiffuseDepth = 0.0, output float GlossyDepth = 0.0, output float TransparentDepth = 0.0, - output float TransmissionDepth = 0.0) + output float TransmissionDepth = 0.0, + output float PortalDepth = 0.0) { IsCameraRay = raytype("camera"); IsShadowRay = raytype("shadow"); @@ -49,4 +50,8 @@ shader node_light_path(output float IsCameraRay = 0.0, int transmission_depth = 0; getattribute("path:transmission_depth", transmission_depth); TransmissionDepth = (float)transmission_depth; + + int portal_depth = 0; + getattribute("path:portal_depth", portal_depth); + PortalDepth = (float)portal_depth; } diff --git a/intern/cycles/kernel/svm/light_path.h b/intern/cycles/kernel/svm/light_path.h index f5d13b5f12a..3e52cb12124 100644 --- a/intern/cycles/kernel/svm/light_path.h +++ b/intern/cycles/kernel/svm/light_path.h @@ -11,7 +11,8 @@ CCL_NAMESPACE_BEGIN /* Light Path Node */ template -ccl_device_noinline void svm_node_light_path(ConstIntegratorGenericState state, +ccl_device_noinline void svm_node_light_path(KernelGlobals kg, + ConstIntegratorGenericState state, const ccl_private ShaderData *sd, ccl_private float *stack, const uint type, @@ -92,6 +93,12 @@ ccl_device_noinline void svm_node_light_path(ConstIntegratorGenericState state, info = (float)integrator_state_transmission_bounce(state, path_flag); } break; + case NODE_LP_ray_portal: + IF_KERNEL_NODES_FEATURE(LIGHT_PATH) + { + info = (float)integrator_state_portal_bounce(kg, state, path_flag); + } + break; } stack_store_float(stack, out_offset, info); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 6f76a17b2c5..a529b8cce9d 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -323,7 +323,7 @@ ccl_device void svm_eval_nodes(KernelGlobals kg, svm_node_brightness(stack, node.y, node.z, node.w); break; SVM_CASE(NODE_LIGHT_PATH) - svm_node_light_path(state, sd, stack, node.y, node.z, path_flag); + svm_node_light_path(kg, state, sd, stack, node.y, node.z, path_flag); break; SVM_CASE(NODE_OBJECT_INFO) svm_node_object_info(kg, sd, stack, node.y, node.z); diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index a1ede05ab15..1663a6b6d5e 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -22,6 +22,7 @@ CCL_NAMESPACE_BEGIN enum ShaderNodeType { #define SHADER_NODE_TYPE(name) name, #include "node_types_template.h" + NODE_NUM }; @@ -101,6 +102,7 @@ enum NodeLightPath { NODE_LP_ray_glossy, NODE_LP_ray_transparent, NODE_LP_ray_transmission, + NODE_LP_ray_portal, }; enum NodeLightFalloff { diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 3db3c0cbde5..ce47b3af627 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -80,78 +80,82 @@ CCL_NAMESPACE_BEGIN #define KERNEL_FEATURE_NODE_AOV (1U << 7U) #define KERNEL_FEATURE_NODE_LIGHT_PATH (1U << 8U) #define KERNEL_FEATURE_NODE_PRINCIPLED_HAIR (1U << 9U) +#define KERNEL_FEATURE_NODE_PORTAL (1U << 10U) /* Use path tracing kernels. */ -#define KERNEL_FEATURE_PATH_TRACING (1U << 10U) +#define KERNEL_FEATURE_PATH_TRACING (1U << 11U) /* BVH/sampling kernel features. */ -#define KERNEL_FEATURE_POINTCLOUD (1U << 11U) -#define KERNEL_FEATURE_HAIR (1U << 12U) -#define KERNEL_FEATURE_HAIR_THICK (1U << 13U) -#define KERNEL_FEATURE_OBJECT_MOTION (1U << 14U) +#define KERNEL_FEATURE_POINTCLOUD (1U << 12U) +#define KERNEL_FEATURE_HAIR (1U << 13U) +#define KERNEL_FEATURE_HAIR_THICK (1U << 14U) +#define KERNEL_FEATURE_OBJECT_MOTION (1U << 15U) /* Denotes whether baking functionality is needed. */ -#define KERNEL_FEATURE_BAKING (1U << 15U) +#define KERNEL_FEATURE_BAKING (1U << 16U) /* Use subsurface scattering materials. */ -#define KERNEL_FEATURE_SUBSURFACE (1U << 16U) +#define KERNEL_FEATURE_SUBSURFACE (1U << 17U) /* Use volume materials. */ -#define KERNEL_FEATURE_VOLUME (1U << 17U) +#define KERNEL_FEATURE_VOLUME (1U << 18U) /* Use Transparent shadows */ -#define KERNEL_FEATURE_TRANSPARENT (1U << 18U) +#define KERNEL_FEATURE_TRANSPARENT (1U << 19U) /* Use shadow catcher. */ -#define KERNEL_FEATURE_SHADOW_CATCHER (1U << 19U) +#define KERNEL_FEATURE_SHADOW_CATCHER (1U << 20U) /* Light render passes. */ -#define KERNEL_FEATURE_LIGHT_PASSES (1U << 20U) +#define KERNEL_FEATURE_LIGHT_PASSES (1U << 21U) /* AO. */ -#define KERNEL_FEATURE_AO_PASS (1U << 21U) -#define KERNEL_FEATURE_AO_ADDITIVE (1U << 22U) +#define KERNEL_FEATURE_AO_PASS (1U << 22U) +#define KERNEL_FEATURE_AO_ADDITIVE (1U << 23U) #define KERNEL_FEATURE_AO (KERNEL_FEATURE_AO_PASS | KERNEL_FEATURE_AO_ADDITIVE) /* MNEE. */ -#define KERNEL_FEATURE_MNEE (1U << 23U) +#define KERNEL_FEATURE_MNEE (1U << 24U) /* Path guiding. */ -#define KERNEL_FEATURE_PATH_GUIDING (1U << 24U) +#define KERNEL_FEATURE_PATH_GUIDING (1U << 25U) /* OSL. */ -#define KERNEL_FEATURE_OSL_SHADING (1U << 25U) -#define KERNEL_FEATURE_OSL_CAMERA (1U << 26U) +#define KERNEL_FEATURE_OSL_SHADING (1U << 26U) +#define KERNEL_FEATURE_OSL_CAMERA (1U << 27U) /* Light and shadow linking. */ -#define KERNEL_FEATURE_LIGHT_LINKING (1U << 27U) -#define KERNEL_FEATURE_SHADOW_LINKING (1U << 28U) +#define KERNEL_FEATURE_LIGHT_LINKING (1U << 28U) +#define KERNEL_FEATURE_SHADOW_LINKING (1U << 29U) /* Use denoising kernels and output denoising passes. */ -#define KERNEL_FEATURE_DENOISING (1U << 29U) +#define KERNEL_FEATURE_DENOISING (1U << 30U) /* Light tree. */ -#define KERNEL_FEATURE_LIGHT_TREE (1U << 30U) +#define KERNEL_FEATURE_LIGHT_TREE (1U << 31U) /* Shader node feature mask, to specialize shader evaluation for kernels. */ #define KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT \ (KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_VORONOI_EXTRA | \ - KERNEL_FEATURE_NODE_LIGHT_PATH) + KERNEL_FEATURE_NODE_LIGHT_PATH | KERNEL_FEATURE_NODE_PORTAL) #define KERNEL_FEATURE_NODE_MASK_SURFACE_BACKGROUND \ (KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT | KERNEL_FEATURE_NODE_AOV) #define KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW \ (KERNEL_FEATURE_NODE_BSDF | KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_BUMP | \ KERNEL_FEATURE_NODE_BUMP_STATE | KERNEL_FEATURE_NODE_VORONOI_EXTRA | \ - KERNEL_FEATURE_NODE_LIGHT_PATH | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR) + KERNEL_FEATURE_NODE_LIGHT_PATH | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR | \ + KERNEL_FEATURE_NODE_PORTAL) #define KERNEL_FEATURE_NODE_MASK_SURFACE \ (KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW | KERNEL_FEATURE_NODE_RAYTRACE | \ KERNEL_FEATURE_NODE_AOV | KERNEL_FEATURE_NODE_LIGHT_PATH) #define KERNEL_FEATURE_NODE_MASK_VOLUME \ (KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_VOLUME | \ - KERNEL_FEATURE_NODE_VORONOI_EXTRA | KERNEL_FEATURE_NODE_LIGHT_PATH) + KERNEL_FEATURE_NODE_VORONOI_EXTRA | KERNEL_FEATURE_NODE_LIGHT_PATH | \ + KERNEL_FEATURE_NODE_PORTAL) #define KERNEL_FEATURE_NODE_MASK_DISPLACEMENT \ - (KERNEL_FEATURE_NODE_VORONOI_EXTRA | KERNEL_FEATURE_NODE_BUMP | KERNEL_FEATURE_NODE_BUMP_STATE) + (KERNEL_FEATURE_NODE_VORONOI_EXTRA | KERNEL_FEATURE_NODE_BUMP | \ + KERNEL_FEATURE_NODE_BUMP_STATE | KERNEL_FEATURE_NODE_PORTAL) #define KERNEL_FEATURE_NODE_MASK_BUMP KERNEL_FEATURE_NODE_MASK_DISPLACEMENT /* Must be constexpr on the CPU to avoid compile errors because the state types diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index e3c37535e60..ca6b1de444e 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -643,6 +643,7 @@ static void log_kernel_features(const uint features) LOG_INFO << "Use Subsurface " << string_from_bool(features & KERNEL_FEATURE_SUBSURFACE); LOG_INFO << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_VOLUME); LOG_INFO << "Use Shadow Catcher " << string_from_bool(features & KERNEL_FEATURE_SHADOW_CATCHER); + LOG_INFO << "Use Portal Node " << string_from_bool(features & KERNEL_FEATURE_NODE_PORTAL); } bool Scene::load_kernels(Progress &progress) diff --git a/intern/cycles/scene/shader_graph.h b/intern/cycles/scene/shader_graph.h index 06f11d2f84a..ece60504346 100644 --- a/intern/cycles/scene/shader_graph.h +++ b/intern/cycles/scene/shader_graph.h @@ -232,7 +232,7 @@ class ShaderNode : public Node { * so it's possible to disable huge nodes inside of the required * nodes group. */ - virtual int get_feature() + virtual uint get_feature() { return bump == SHADER_BUMP_NONE ? 0 : KERNEL_FEATURE_NODE_BUMP; } diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 64bd67ba48d..516e5ff6338 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -4123,6 +4123,7 @@ NODE_DEFINE(LightPathNode) SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth"); SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth"); SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth"); + SOCKET_OUT_FLOAT(portal_depth, "Portal Depth"); return type; } @@ -4202,6 +4203,11 @@ void LightPathNode::compile(SVMCompiler &compiler) if (!out->links.empty()) { compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out)); } + + out = output("Portal Depth"); + if (!out->links.empty()) { + compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_portal, compiler.stack_assign(out)); + } } void LightPathNode::compile(OSLCompiler &compiler) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 823c213b66e..91c9e01dc6e 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -266,7 +266,7 @@ class VoronoiTextureNode : public TextureNode { public: SHADER_NODE_CLASS(VoronoiTextureNode) - int get_feature() override + uint get_feature() override { int result = ShaderNode::get_feature(); if (dimensions == 4) { @@ -462,7 +462,7 @@ class BsdfBaseNode : public ShaderNode { return false; } - int get_feature() override + uint get_feature() override { return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_BSDF; } @@ -578,6 +578,11 @@ class RayPortalBsdfNode : public BsdfNode { { return true; } + + uint get_feature() override + { + return BsdfNode::get_feature() | KERNEL_FEATURE_NODE_PORTAL; + } }; class SheenBsdfNode : public BsdfNode { @@ -725,7 +730,7 @@ class EmissionNode : public ShaderNode { return true; } - int get_feature() override + uint get_feature() override { return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_EMISSION; } @@ -747,7 +752,7 @@ class BackgroundNode : public ShaderNode { return true; } - int get_feature() override + uint get_feature() override { return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_EMISSION; } @@ -781,7 +786,7 @@ class AmbientOcclusionNode : public ShaderNode { { return true; } - int get_feature() override + uint get_feature() override { return KERNEL_FEATURE_NODE_RAYTRACE; } @@ -808,7 +813,7 @@ class VolumeNode : public ShaderNode { ShaderInput *density, ShaderInput *param1 = nullptr, ShaderInput *param2 = nullptr); - int get_feature() override + uint get_feature() override { return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_VOLUME; } @@ -933,7 +938,7 @@ class PrincipledHairBsdfNode : public BsdfBaseNode { /* Selected scattering model (chiang/huang). */ NODE_SOCKET_API(NodePrincipledHairModel, model) - int get_feature() override + uint get_feature() override { return ccl::BsdfBaseNode::get_feature() | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR; } @@ -1510,7 +1515,7 @@ class BumpNode : public ShaderNode { { return true; } - int get_feature() override + uint get_feature() override { return KERNEL_FEATURE_NODE_BUMP; } @@ -1634,7 +1639,7 @@ class OSLNode final : public ShaderNode { { return true; } - int get_feature() override + uint get_feature() override { return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_RAYTRACE; } @@ -1693,7 +1698,7 @@ class BevelNode : public ShaderNode { { return true; } - int get_feature() override + uint get_feature() override { return KERNEL_FEATURE_NODE_RAYTRACE; } @@ -1707,7 +1712,7 @@ class DisplacementNode : public ShaderNode { public: SHADER_NODE_CLASS(DisplacementNode) void constant_fold(const ConstantFolder &folder) override; - int get_feature() override + uint get_feature() override { return KERNEL_FEATURE_NODE_BUMP; } @@ -1728,7 +1733,7 @@ class VectorDisplacementNode : public ShaderNode { return true; } void constant_fold(const ConstantFolder &folder) override; - int get_feature() override + uint get_feature() override { return KERNEL_FEATURE_NODE_BUMP; } diff --git a/intern/cycles/scene/svm.cpp b/intern/cycles/scene/svm.cpp index 13e561a8467..a3d4465a837 100644 --- a/intern/cycles/scene/svm.cpp +++ b/intern/cycles/scene/svm.cpp @@ -495,7 +495,7 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state) { /* Skip generating closure that are not supported or needed for a particular * type of shader. For example a BSDF in a volume shader. */ - const int node_feature = node->get_feature(); + const uint node_feature = node->get_feature(); if ((state->node_feature_mask & node_feature) != node_feature) { return; } diff --git a/scripts/startup/bl_ui/node_add_menu_shader.py b/scripts/startup/bl_ui/node_add_menu_shader.py index 29353eea5c0..8dc3d63e708 100644 --- a/scripts/startup/bl_ui/node_add_menu_shader.py +++ b/scripts/startup/bl_ui/node_add_menu_shader.py @@ -103,7 +103,8 @@ class NODE_MT_category_shader_input(Menu): "Diffuse Depth", "Glossy Depth", "Transparent Depth", - "Transmission Depth" + "Transmission Depth", + "Portal Depth" ], ) node_add_menu.add_node_type_with_outputs( diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl index d36a3128ff3..9ed2b78855d 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl @@ -15,7 +15,8 @@ void node_light_path(out float is_camera_ray, out float diffuse_depth, out float glossy_depth, out float transparent_depth, - out float transmission_depth) + out float transmission_depth, + out float path_depth) { /* Supported. */ is_camera_ray = float(g_data.ray_type == RAY_TYPE_CAMERA); @@ -34,4 +35,5 @@ void node_light_path(out float is_camera_ray, /* Not supported. */ transparent_depth = 0.0f; is_volume_scatter_ray = 0.0f; + path_depth = 0.0f; } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.cc b/source/blender/nodes/shader/nodes/node_shader_light_path.cc index 75fc41f2984..77af4ec502f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_path.cc +++ b/source/blender/nodes/shader/nodes/node_shader_light_path.cc @@ -22,6 +22,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Glossy Depth"); b.add_output("Transparent Depth"); b.add_output("Transmission Depth"); + b.add_output("Portal Depth"); } static int node_shader_gpu_light_path(GPUMaterial *mat, diff --git a/tests/files/render/integrator/cycles_renders/light_path_portal_depth.png b/tests/files/render/integrator/cycles_renders/light_path_portal_depth.png new file mode 100644 index 00000000000..c3fa0185297 --- /dev/null +++ b/tests/files/render/integrator/cycles_renders/light_path_portal_depth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d1083f2080d583bab4b4f4f1638aa811021f980e9fe7d7f2b8c6f4c0cdaa8ea +size 9643 diff --git a/tests/files/render/integrator/eevee_renders/light_path_portal_depth.png b/tests/files/render/integrator/eevee_renders/light_path_portal_depth.png new file mode 100644 index 00000000000..68b8e4d52d8 --- /dev/null +++ b/tests/files/render/integrator/eevee_renders/light_path_portal_depth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b9d931c52f90a12d46a6e445eefea70c54c0c463c5590c468fc6576c28a2bdc +size 9304 diff --git a/tests/files/render/integrator/light_path_portal_depth.blend b/tests/files/render/integrator/light_path_portal_depth.blend new file mode 100644 index 00000000000..721d2fea688 --- /dev/null +++ b/tests/files/render/integrator/light_path_portal_depth.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:474e970fdc801ef7711714b676215f657ff8362bcf7780a0b3c917c993b05425 +size 113143 diff --git a/tests/files/render/integrator/storm_hydra_renders/light_path_portal_depth.png b/tests/files/render/integrator/storm_hydra_renders/light_path_portal_depth.png new file mode 100644 index 00000000000..d9f33ad891d --- /dev/null +++ b/tests/files/render/integrator/storm_hydra_renders/light_path_portal_depth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b555cbce5bcccae75cd0d5faf7eb9810feae2c672ab3cf374695e86b46d8ac4 +size 8437 diff --git a/tests/files/render/integrator/storm_usd_renders/light_path_portal_depth.png b/tests/files/render/integrator/storm_usd_renders/light_path_portal_depth.png new file mode 100644 index 00000000000..c7d177c4995 --- /dev/null +++ b/tests/files/render/integrator/storm_usd_renders/light_path_portal_depth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1dd8f1b05c8e3c4fb386c35afeece5aeefbd659ccc7bdb4b8911fb3080360f8d +size 8437 diff --git a/tests/files/render/integrator/workbench_renders/light_path_portal_depth.png b/tests/files/render/integrator/workbench_renders/light_path_portal_depth.png new file mode 100644 index 00000000000..721266b133e --- /dev/null +++ b/tests/files/render/integrator/workbench_renders/light_path_portal_depth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22495afac799fbd0979448fdf454695973e24096488030fe01d9712c335b33c5 +size 14054