react-three-renderer
react-three-renderer copied to clipboard
What are the rules for <resources /> ?
Can you clarify what the rules for the <resources /> object is? I'm not sure when I can access a resources from a different part of my component tree, etc. Some specific questions are below.
- In individual component, can I reference a
resourceIddeclared a parent component? - Can I use a resource not defined in a parent component, but defined in a sibling component? As in, are resource names considered global to the render tree?
- Can I define multiple
<resouce>tags in the same component? - What happens if, in any place, I duplicate a resource /
resourceIdbetween components? Will the user of the resource look up the render tree until it finds one, or are they global and the "last" one wins? - To what degree does render order matter for resources? If I
referenceIda resource in a sibling component, the sibling might not have been created yet. Will this fail, or does it all get batched together at render time and sorted before render? - What happens if I modify runtime properties of a resource at runtime? For example, I want to change the opacity of a material. Is this allowed / safe / efficient?
- In individual component, can I reference a resourceId declared a parent component?
- Yes
- Can I use a resource not defined in a parent component, but defined in a sibling component? As in, are resource names considered global to the render tree?
- Not siblings, resources aren't global
- Can I define multiple
tags in the same component? <resource-like>(all within https://github.com/toxicFork/react-three-renderer/wiki/Resource-Types) tags can go only within<resources>in a component, and yes you can have multiple<resource-like>tags inside a<resources>tag. I have not tried multiple<resources>tag within a component.
- What happens if, in any place, I duplicate a resource / resourceId between components? Will the user of the resource look up the render tree until it finds one, or are they global and the "last" one wins?
-
This is a fun one. If a parent P has let's say resource for id 'foo', and a child C has resource for id 'foo', the references within the child C (and its children and grandchildren and so on) will use the inner foo. The parent's children (e.g. any siblings of child and these siblings' children) excluding this child C will use the outer one. So the 'nearest above' wins.
<group> // group 1 start <resources> <meshBasicMaterial resourceId='foo' color={redColor}/> </resources> <mesh> <materialResource resourceId='foo' // this will be red /> </mesh> <group> // group 2 start <resources> <meshBasicMaterial resourceId='foo' color={greenColor}/> </resources> <mesh> <materialResource resourceId='foo' // this will be green /> </mesh> <group> // group 3 start <resources> <meshBasicMaterial resourceId='foo' color={blueColor}/> </resources> <mesh> <materialResource resourceId='foo' // this will be blue /> </mesh> <group> // group 4 start <mesh> <materialResource resourceId='foo' // this will be blue too /> </mesh> <group> // group 5 start <mesh> <materialResource resourceId='foo' // this will be blue too /> </mesh> </group> // group 5 end </group> // group 4 end <mesh> <materialResource resourceId='foo' // this will be blue /> </mesh> </group> // group 3 end <mesh> <materialResource resourceId='foo' // this will be green /> </mesh> </group> // group 2 end <mesh> <materialResource resourceId='foo' // this will be red /> </mesh> </group> // group 1 end
-
- To what degree does render order matter for resources? If I referenceId a resource in a sibling component, the sibling might not have been created yet. Will this fail, or does it all get batched together at render time and sorted before render?
-
It is recommend to place
<resources/>as the first element of any component because of multiple reasons:-
It will be constructed before any other siblings, and anything within them will also be constructed first.
e.g. render order
<group> // 7 <resources> // 3 <a/> // 1 <b/> // 2 </resources> <mesh> // 4 </mesh> <group> // 6 <mesh/> // 5 </group> </group>- This is not a huge issue, since after the resources are constructed the previous siblings references will be filled in, but it's not really nice as they may be re-rendered which can be expensive.
-
If any of the siblings BEFORE it get added or removed, then (because of how react renders) ALL of the resources within may get re-constructed which is super expensive and against all that is good in the world. This CAN be prevented if you place a
keyproperty on the resource, but that still means the objects before this may not be properly initialized.
-
-
Resources within a sibling cannot be referred to.
<parent> <child-a> <resources> </resources> </child-a> <child-b> You cannot refer to anything in `<child a/>` here </child-b> </parent>
-
- What happens if I modify runtime properties of a resource at runtime? For example, I want to change the opacity of a material. Is this allowed / safe / efficient?
-
It's not only safe and efficient, it's even recommended! That's one of the main purposes for resources. You can use resources to change the color of a material for any number of meshes this way, e.g.
<group> <resources> <meshBasicMaterial resourceId="mat1" color={>>change this<<}/> // ... geometry... resourceId="geom1" </resources> <Meshes/> </group> Meshes.prototype.render = () => { // all meshes refer to the same material and geometry instances return (<group> <mesh> <materialResource resourceId="mat1"/> <geometryResource resourceId="geom1"/> </mesh> <mesh> <materialResource resourceId="mat1"/> <geometryResource resourceId="geom1"/> </mesh> <mesh> <materialResource resourceId="mat1"/> <geometryResource resourceId="geom1"/> </mesh> // ... and so on </group>) }
-
I will add these in a FAQ :) It's a complex little beast!
Updated comment above