Three.js: Unity compatible per-material render order support

Created on 26 Mar 2019  Β·  16Comments  Β·  Source: mrdoob/three.js

Already discussed a bit on #14415

We already have renderOrder for meshes and groups,
but not for materials, which is supported by Unity (as renderQueue).
It would help sorting rendering order of multi-material meshes in certain condition.

I have no idea how much the idea makes good impact for us but I need this at least (πŸ™„),
Since I have to display Unity-compatible stuff (I mean, VRM) on https://hub.vroid.com ...

demo below
https://codepen.io/FMS-Cat/pen/pYBwzw

Won't fix

Most helpful comment

Closing for now. I think we agree to not introduce Material.renderOrder. As mentioned by @WestLangley, the engine sorts and renders objects, so it's better if renderOrder is only related to Object3D.

If a user really needs to sort the derived render items of a multi material object, the idea is the transform the object into multiple ones and use Object3D.renderOrder again. In other words, this (special) use case needs to be solved on application level.

All 16 comments

If I understand your pen correctly, you can only achieve your intended visual result right now if you split up the geometry into two, create two meshes, apply different materials and then use Object3D.renderOrder, correct?

Yes, and that's why I said I don't know how the idea help us.
I don't think merging two or more meshes into one geometry makes us happy in this situation.

Plus, we currently don't have scene description format that describes rendering order of submeshes or materials
(other than VRM, which is unpolished and still wip).

I think the change doesn't cause large impact on both codebase and performance though,
and might help some niche cases (like us πŸ™„).

Actual our case in VRoid Hub can be seen on the slide below (Japanese πŸ™‡):

https://speakerdeck.com/fms_cat/webshi-jie-tejun-false3dmoterunisheng-wochui-kiip-mufang-fa?slide=42

We currently are addressing the issue by replacing the WebGLRenderLists for our own one.

It would help sorting rendering order of multi-material meshes in certain condition.

Note that in upcoming r103, GLTFLoader will no longer create multi-material meshes. If it's still a dependency of VRMLoader that may affect this issue.

in upcoming r103, GLTFLoader will no longer create multi-material meshes

https://github.com/mrdoob/three.js/pull/15889

What, I didn't know that!

The PR sounds like we should avoid to use the multi-material meshes...?

All glTF files that worked before should still workβ€” each primitive (or material) in a glTF mesh will now become a separate threejs Mesh when loaded.

Yes I acknowledged that, and then I no longer need the feature request anymore πŸ˜…

Separating into meshes affects to performance though (at bone update section),
so I might rather use previous merging method anyway.

Plus, since VRM have renderQueue information for materials
then if we can have renderOrder property for materials it still would be more clean and cool.

Just to clarify: Material.renderOrder is useful for sorting the render order of render items derived from a multi material mesh. If you just have meshes with one material, you could put the information from your render queue directly to Mesh.renderOrder, right?

Just to clarify: Material.renderOrder is useful for sorting the render order of render items derived from a multi material mesh.

Maybe instead of hardwiring in the renderer:

groupOrder = object.renderOrder;

Maybe we should do this:

addGroup: function ( start, count, materialIndex, groupOrder ) {

    this.groups.push( {

        start: start,
        count: count,
        materialIndex: materialIndex !== undefined ? materialIndex : 0,
        groupOrder: groupOrder !== undefined ? groupOrder : 0

    } );

},

It's the object that needs to be sorted, not the material.

I think it's important not to mix THREE.Group and BufferGeometry.groups. The first code snippet from projectObject() is for the case you assign a render order to an instance of THREE.Group. This enables nested sorting in the scene graph via Object3D.renderOrder. BufferGeometry.groups is only relevant for multi material objects. The derived render items can't be sorted right now via Object3D.renderOrder and I guess that is @FMS-Cat problem. I would not change the semantics of groupOrder but rather introduce Material.renderOrder.

OK.

But still, objects can share materials. Material.renderOrder does not make sense to me. We render and sort renderable objects, not materials.

I agree. Unity allows to influence the render order on material/shader level (see https://docs.unity3d.com/Manual/SL-SubShaderTags.html) whereas three.js does this on object level. Hence, it feels inconsistent to introduce Material.renderOrder.

Even if Material.renderOrder would be introduced, the feature would not be compatible to Unity's approach like suggested in the issue's title. For example the value of renderOrder is "relative" to each render list (opaque and transparent objects). Unity's render queue value is global instead.

So the question is now, how about my suggestion above, adding

BufferGeometry.groups[ i ].renderOrder

But even so, this is such an edge case...

If you just have meshes with one material, you could put the information from your render queue directly to Mesh.renderOrder, right?

True.

the value of renderOrder is "relative" to each render list (opaque and transparent objects). Unity's render queue value is global instead.

Yes that is also true, Unity still may use separated render lists internally though,
to achieve opaque should render forward to behind, transparent should render behind to forward.
(and yeah I don't like the way the renderLists gets separated at certain constants (2501 I guess?)).

how about my suggestion above, adding

BufferGeometry.groups[ i ].renderOrder

But even so, this is such an edge case...

Yeah I think so too 😩

Closing for now. I think we agree to not introduce Material.renderOrder. As mentioned by @WestLangley, the engine sorts and renders objects, so it's better if renderOrder is only related to Object3D.

If a user really needs to sort the derived render items of a multi material object, the idea is the transform the object into multiple ones and use Object3D.renderOrder again. In other words, this (special) use case needs to be solved on application level.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jack-jun picture jack-jun  Β·  3Comments

jlaquinte picture jlaquinte  Β·  3Comments

filharvey picture filharvey  Β·  3Comments

akshaysrin picture akshaysrin  Β·  3Comments

konijn picture konijn  Β·  3Comments