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
This commit is contained in:
Sergey Sharybin
2025-07-25 18:09:38 +02:00
committed by Sergey Sharybin
parent efe14ff166
commit dcae48d1d3
27 changed files with 155 additions and 45 deletions

View File

@@ -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;

View File

@@ -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) =

View File

@@ -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 */

View File

@@ -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. */

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -11,7 +11,8 @@ CCL_NAMESPACE_BEGIN
/* Light Path Node */
template<uint node_feature_mask, typename ConstIntegratorGenericState>
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);

View File

@@ -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<node_feature_mask>(state, sd, stack, node.y, node.z, path_flag);
svm_node_light_path<node_feature_mask>(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);

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -22,6 +22,7 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Float>("Glossy Depth");
b.add_output<decl::Float>("Transparent Depth");
b.add_output<decl::Float>("Transmission Depth");
b.add_output<decl::Float>("Portal Depth");
}
static int node_shader_gpu_light_path(GPUMaterial *mat,

Binary file not shown.

Binary file not shown.

BIN
tests/files/render/integrator/light_path_portal_depth.blend (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.