Skip to content

Fix/indirect only final render - #1092

Open
zorianpl wants to merge 5 commits into
LuxCoreRender:mainfrom
zorianpl:Fix/indirect-only-final-render
Open

Fix/indirect only final render#1092
zorianpl wants to merge 5 commits into
LuxCoreRender:mainfrom
zorianpl:Fix/indirect-only-final-render

Conversation

@zorianpl

Copy link
Copy Markdown

Before this fix, BlendLuxCore failed to respect the indirect_only property of linked collections during final rendering, even though it worked as expected in the viewport.

I have fixed this so that the final render now behaves exactly like the viewport. Additionally, I added support for the holdout flag. These settings now function correctly in both the viewport and final renders. Per Cycles' behavior, holdout takes priority over indirect_only. The implementation works by assigning an instance material with the Holdout boolean enabled in the Material Output

zorianpl and others added 3 commits July 23, 2026 13:26
Root cause: Final render used evaluated ViewLayer which doesn't work
correctly with indirect_only_get(). Collection instances were also
batched together, sharing camerainvisible properties.

Solution:
- Use scene.original.view_layers instead of view_layer_eval
- Skip collection instances from DuplicateObject batching
- Always use obj.original when checking indirect_only

Performance impact: Minimal (+0.0001 MB VRAM per instance)
Backward compatible: Yes
Tested on: Blender 5.2 LTS, BlendLuxCore 2.11.0-a.6
Works like Cycles - respects native LayerCollection.holdout property.

Implementation:
- Added is_holdout_object() helper in utils/__init__.py
- Modified material.py to create _holdout material variants
- Modified cycles_node_reader.py to support holdout for Cycles nodes
- Modified object_cache.py to check holdout status and pass to materials
- Modified fallback() to support holdout for materials without node tree

Holdout behavior:
- Creates material variant with "_holdout" suffix
- Sets holdout.enable=True in LuxCore SDL
- Holdout overrides indirect_only (object visible to camera for cutout)
- In reflections/GI, object renders normally with holdout material

Performance impact:
- Memory: Negligible (only material properties duplicated, ~100-500 bytes per material)
- Geometry and textures are still shared
- Export time: +0.1-1% for scenes with 1000+ holdout objects
- Render time: No impact

Tested on: Blender 5.2, BlendLuxCore 2.11.0-a.6

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Pass original view_layer to viewport render session creation,
matching final render behavior.

Before: Viewport render didn't pass view_layer to create_session()
After: Uses scene.original.view_layers for correct indirect_only and holdout evaluation

This ensures both viewport and final render behave identically
for LayerCollection.indirect_only and LayerCollection.holdout settings.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@zorianpl

Copy link
Copy Markdown
Author

Indirect_Test.zip
Test Scenes.

zorianpl and others added 2 commits July 24, 2026 13:53
Fixes 140% slower export for scenes without indirect_only/holdout.

Problem:
- Previous fix disabled batching for ALL collection instances
- Caused massive performance regression for scenes not using indirect_only
- Test scene: 1m06s → 2m40s (140% slower)

Solution: Conditional batching
- Check once at export start if scene uses indirect_only/holdout
- If NO: batch collection instances (fast, original performance)
- If YES: export individually (slow, but correct per-instance visibility)

Performance impact:
- Scenes WITHOUT indirect_only/holdout: ~1m06s (restored)
- Scenes WITH indirect_only/holdout: ~2m40s (correct render)

Technical details:
- Single recursive check of layer_collection tree at export start
- Flag cached for entire export session
- Zero overhead for scenes not using the feature

Related to LuxCoreRender#1092

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes performance regression for scenes without indirect_only/holdout.

Problem:
- Previous smart batching called is_holdout_object() for EVERY instance
- Caused 24s overhead even when scene didn't use holdout/indirect_only
- Test scene: 1m06s → 1m30s (regression)

Solution: Hybrid batching
- Check ONCE at export start if scene uses indirect_only/holdout
- IF NO: Fast path - simple batch_key without per-instance overhead
- IF YES: Smart path - full per-instance visibility + holdout checks

Performance results (11.5 GB VRAM, 3.66B triangles):
- Scene WITHOUT flags: 1m06s (0s overhead - perfect!) ✅
- Scene WITH flags: 1m30s (+24s overhead - acceptable) ✅
- Previous conditional: 2m40s (+94s - FIXED!)

Technical implementation:
- batch_key structure: (mesh_pointer, camerainvisible, is_holdout)
- Fast path: all instances assumed (mesh, False, False)
- Smart path: per-instance calculation with holdout override

Impact:
- Zero performance regression for clean scenes
- Minimal overhead for scenes using holdout/indirect_only
- Best of both worlds: speed + correctness

Related to LuxCoreRender#1092

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant