Possible Implementation for Light Linking
--
UPDATE as of 5/18/21: I actually got Brecht van Lommel (original creator of Cycles and still one of its main developers) to look at this, and this is what he said: "this is much too complicated, if we implement light linking it will be similar to how it's done in other software, not an entirely different mechanism. Note that tracing rays from the light only is also very inefficient. certainly bidirectional tracing would be useful, but that still traces rays from the camera too. Light linking (and other features to control shading) should be implemented in a way that they do not require any particular rendering algorithm." So suffice it to say that if/when light linking gets implemented, it will probably not be like this. I trust Lommel & Co; they know what they're doing. Whatever it looks like, I'm sure it's going to be awesome.
--
(note: I've been editing this post continuously, so if some of the posted comments don't make sense, that's probably why)
I know I don't need to add to the already endless slew of requests for light-linking; what is more helpful is to propose an actual way it could be implemented.
I have come up with a specific way light linking could be implemented that would be intuitive yet utterly comprehensive, and 100% "Blender-way". However, I don't think it would work with EEVEE, at least not out of the box; I have a very poor understanding of how EEVEE works.
There is a link-linking node editor; the linking can be "light-centric" or "object-centric." Node setups are connected to an individual light or renderable object. Light-linking node setups are not used by default, but one can be created in the light properties or mesh/curve/metaball/text/etc properties (just like you create a new shader node setup by creating a new material in the material panel, create a new geometry node setup from the modifier panel, etc).
General Node System Explanation
Light Node
A node tree starts with a Light input node, which has a single "ray" output socket.
Object Node
A light ray noodle from a Light node is wired through any number of Object nodes. An object node has:
- a menu to select an object or collection from the scene; leaving this menu blank causes the Object node to represent all objects in the scene.
- multi-input sockets for diffuse, glossy, transmission, and volume; wiring a light ray noodle into one of these sockets allows the corresponding output sockets to give off light from that light ray.
- output sockets for diffuse, glossy, transmission, and volume, which can then wired to a Camera node (see below) to enable the visibility of those aspects of the object, and/or be wired to another Object node to allow them to illuminate the specified aspects of that object. For example, if I connected one object A's glossy output to another object B's diffuse input (assuming object A had a light ray noodle connected to its glossy input socket), then object A's glossy will contribute to object B's diffuse illumination via light bounce.
Camera Node
Any light ray that is to be seen must ultimately be wired into a Camera node, which is an output node with:
- an "invert" checkbox; inverts which light rays are represented by the node tree.
- a single "rays" multi-input socket.
Join Rays Node
Another handy node is the Join Rays node, which is a node with a "rays" multi-input socket and a "ray" output socket; it simply combines multiple rays into one ray, which doesn't impact the final product in any way, as all light is additive and will thus be joined together anyway, but it just helps make the node setup tidier and cuts down on the work for the user when he/she wants to wire the same group of rays into multiple sockets.
Specific Linking Modes
Light-Centric Light Linking
In light-centric linking, any Light node in the setup will refer to the light to which the node setup is attached; multiple Light nodes can be added, but the only reason one might want to do this is for layout purposes in a complex node tree; otherwise it's redundant and pointless.
The initial node tree will consist of a Light node wired into all the inputs of a blank Object node, all of whose outputs are wired into a Camera node with "invert" checked off.
Object-Centric Light Linking
For object-centric light linking, Light nodes have a menu to specify different lights (and, like Object nodes, leaving it blank makes it apply to all lights). Any light ray in the node tree that at no point passes through an Object node that is set to the attached object will be unrepresented in the node tree even if it is wired into the Camera node, because this node tree is focused on the attached object and its interactions with the rest of the scene.
The initial node tree will consist of a blank Light node wired into all the inputs of an Object node set to the attached object, all of whose outputs are wired into a Camera node with "invert" checked off.
How Multiple Node Setups Interact
What if multiple node setups contradict each other? Well, at least in this proposition, a light-linking node setup cannot say "I'm enabling this light ray." It can either say "I'm disabling this light ray" or "I'm not disabling this light ray." This has no impact on whether the light ray gets disabled by another node setup. So bottom line, if a light ray is disabled by a node setup (either by not being represented in a node setup, or by being represented in a node setup with "inverted" checked on), then it is disabled, regardless of whether it is allowed by another node setup. If you think of the node tree as a mask for what light rays get rendered, each node tree's blending mode is "multiply," and they will interact accordingly.
How It Actually Works Under the Hood
I have no familiarity with Blender's underlying code ( yet; I am currently waiting for my copy from Amazon of the book Brad Hollister recently put out about Blender's C code), so I'm getting a little over my head in this section, but here's what I've thought of so far based on what I do know.
Option 1
The way I initially thought this would work is all light rays would be initially calculated as usual (ignoring the nodes). If a calculated light ray reaches a light with a node tree (I know Cycles traces light rays from the camera and renders them if they reach a light source), Cycles then looks at the node tree to see if that light ray is represented, and then uses/ignores it accordingly.
After some thought, I realized that this wastes render time because many light rays are going to be calculated only to be ignored.
Option 2
While I'm sure the Cycles developers have their reasons for tracing light rays from the camera to the light source, it would be much more efficient for this if Cycles calculated rays starting with the light source and then reaching the camera, because then Cycles could work through the node tree as it's tracing the ray , checking each bounce to see if it's represented, and stop calculating the light ray as soon as the ray runs out of paths in the node tree (and it would also know before a ray is even calculated if it requires this comparison simply based off of the light source it starts from, and whether that light source has a node tree attached). However, this optimization wouldn't work if "Invert" is toggled on, because then Cycles will only ignore the light ray if it makes it all the way to the camera, and the light ray would have be fully traced before it can know that. Maybe for that situation, Cycles' current camera-to-light source approach would be the go-to. This may be another reason to implement bi-directional path tracing (which I think Two Minute Papers may have demonstrated to be faster anyway), but that's a topic for another post, and I know I'm not the first person to mention that.
19 Comments
Could you also add a light path max bounces node that allows you to set the number of bounces per ray? This would be great for adding lights to specialized shaders like glass which are dependent on ray bounces.
* @timothy.m * That would also be pretty neat if this were getting implemented
Could a math node be used to increase the intensity of diffuse, glossy, etc independently?
* @timothy.m * That’s an interesting idea; to my knowledge, light linking is usually used just to separate out light passes in order to tweak them individually in post, but the ability to tweak things in render from the node editor would be neat.
How would this work for geometry set with an emission shader?
* @timothy.m * That is a good question; in my experience with software that uses light linking, objects with emissive materials were too weak to use as actual light sources, so that question never required addressing. Maybe object nodes could have an additional emission output.
* @christsdude * Or the "Light node" could have a drop down option for emissive geometry? I don't know how that would complicate things but I'm sure they're a elegant solution that would encompass it.
Could you add an input for collections, not just one object? That would make it so much easier instead of adding one node per object.
* @timothy.m * I actually mention that the object node can load collections as well as individual objects, but I only mention it once in the entire post, so I definitely don’t blame you for missing it lol. I absolutely agree that it would be a pain to have to load a whole group objects one at a time
I wanted to attach images of the nodes, but I can't figure out how to attach local images from my pc using the markdown syntax.
Try some image host. I use Imgur , work well for me many years. You need to use markdown like this (on image) to link image
Sorry I don't comment light linking - I'm too far from rendering ;)
* @IIIFGIII * I'm getting the same result as when I tried to upload a local file; does the image have to be public on imgur?
* @IIIFGIII * I actually just realized that the image might simply not be displaying on my end; is it displaying for you?
* @christsdude * Nope. You do something wrong.
Also, I see you completely new to this place. Try to write less words. Honestly - people here way tooo lazy to read such essay.... Lot of thoughts - no one interested to read all this , short and simple with one GIF - much better :)
* @IIIFGIII * Ok I guess I needed to make the image public
* @christsdude * Now it work. Congratulations !!!
* @IIIFGIII * Just saw your tip now; thanks, I appreciate it!
And also with couple of features like Light Mixing and Light Groups, Blender can really become more like the industry standard software Foundry Katana.
What about light collections? Every light can have a collection "parented" and all objects inside are affected by it or not affected i you choose to negate it...
* @Topeich * That's definitely another viable approach, although I don't think it really offers the precision of control that I think would be super helpful, like specifying specific sequences of light bounces between certain objects