question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Child opacity relative to parent opacity

See original GitHub issue

Currently, it’s inconvenient and error-prone to change the transparency of an entire object, where the object is subtree (not just a single Mesh, but a hierarchy of objects and meshes). There isn’t a simple way to, for example, fade out an entire car where the car consists of sub-objects like wheels, doors, windshields, etc.

Currently, we traverse the sub tree and manually set opacities on each mesh of the sub tree. F.e., like the following answers:

The problem with the current approaches:

  • prevents encapsulation: couples parent effect (opacity) to child state (child opacities).
    • This is undesirable because it means, if we are dealing with an object who’s subtree is generated and managed by third-party code or the code from some other team (f.e. in a big project), then modifying child state can conflict with the external code that may be modifying the same state, which can cause bugs)
    • In CSS applications (mainly 2D apps because opacity on 3D DOM is straight weird), opacity is relative to the parent, which prevents interference with child state. The children and manipulators of the children don’t have to be aware of parent opacity. It makes it easy to, for example, fade out an entire drop down menu without having to loop on all the sub-menu items.
  • The process is complicated and error prone, which doesn’t lend to an easy-to-use scene graph, which I think is Three’s goal to have, and that in general is very useful for any scene graph to have.

Solution:

There are two possible solutions, and both should be optional so that it is backwards-compatible:

  1. Simple multiplicative opacity that can be set on an Object3D (and any objects that inherit from it) so that opacities are multiplied down the tree just like with transform matrices.
    • I am aware that this means that parts of a whole object that are inside each other will become visible, just like in this SO post. This is okay, and can be fine in many cases.
  2. Still-simple-to-use but more-complicated-implementation opacity that involves rendering an object that has been specified to have a group opacity to a render target to be composed back into the scene, just like in the second screenshot of that same SO post.
    • This obviously costs more resources and is slower
    • It can lead to better visual effects.

Personally, it’d be great to have both types of opacity, and for both of them to be as simple as specifying opacity or groupOpacity on an Object3D, and for the engine to take care of the rest. So that this is all very easy for the end user.

Both options should be completely opt-in, so that they don’t affect current programs that may already be doing these sorts of things in their own way.

API might look like this:

const someObjectThatHasChildren = new Object3D

// ... add a subtree to someObjectThatHasChildren, including Meshes ...

Then either

someObjectThatHasChildren.opacity = 0.3

or

someObjectThatHasChildren.groupedOpacity = 0.3

It would be possible for both opacities to be applied. For example, if we did

someObjectThatHasChildren.opacity = 0.3
someObjectThatHasChildren.groupedOpacity = 0.3

Then, first the group opacity would cause the whole subtree to be rendered to a new target, then while rendering to the new target the non-group opacity would come into play. So, on the separate render target, objects would be rendered with opacity relative to a parent of opacity 0.3, then once the object is composed back into the main scene, it would be rendered at a further 0.3 opacity of that result (in total, 0.3 * 0.3.

If we do it that way, then handling the non-group oacity is completely decoupled from the grouped opacity, and their maintaining them both is not coupled and modifying one feature does not affect the other feature.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:5
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
corbanbrookcommented, May 2, 2019

@trusktr Been running up against this problem as well, wondering if you came across a solution.

How are other people approaching the problem of fading in/out a model that contains multiple materials of varying opacity?

My solution is to traverse the model root and then, keep track of the child material original opacity on its userData. Then set the material.opacity to origOpacity * globalOpacity.

The one potential pit fall is remembering to keep origOpacity in sync when you legitimately need to adjust a materials opacity. To borrow your example above with a model of a car, if you were building a car customizer tool and one option was the window tinting, you would need to keep origOpacity in sync whenever you adjusted the materials properties, other wise the fade out of the car wouldn’t work exactly as expected.

2reactions
Usnulcommented, Feb 28, 2018

Few problems

  • opacity is not free, it’s actually a separate pass in the renderer
  • opacity doesn’t work as you might think it does. Especially when it comes to penetration
  • it doesn’t make sense to have opacity on an object. E.g what’s a transparent camera or a light?
  • extension of previous point: not all materials have opacity, and forcing them to, would make the convoluted process of creating a custom material even harder. Whats a transparent clay brick? My fog of war shader has no opacity, what now? What would it mean for fog of war object to have children?

Tl;dr I think it’s not a good design

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to set opacity in parent div and not affect in child div?
The solution is to use a different element composition, usually using fixed or computed positions for what is today defined as a child...
Read more >
How to change parent opacity without altering child opacity
If all you want to do is alter the opacity of the background-color of the parent, you can use an rgba() color in...
Read more >
CSS Opacity That Doesn't Affect Child Elements
The problem occurs when we add child elements to the html element that this code affects. All child elements will inherit the same...
Read more >
Opacity of child element - CSS-Tricks
A child element's opacity will never be greater than that of its parent. Whatever your use-case there will be a work-around. May 28,...
Read more >
How to set opacity in parent div and not affect in child div
<div class="parent">. <div class="child">. Hello I am child. </div>. </div> .parent{. width:300px;. height:300px;. position:relative;. border:1px solid red;. }.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found