Changing visibility of individual instances?

Hello,

I would like to customize visibility of every single instance (InstancedMesh).

  1. First I tried to set InstancedMesh.visibility, but using this API does not have any effect
  2. Then I tried to use custom buffers with registerInstancedBuffer() API, but this does not seem to work with scalar values (see Babylon.js PlaygroundUncaught TypeError: h.copyToArray is not a function)

Is there any other way I did not try yet?

Hi Iguminski,

This is how I would get it to work: https://playground.babylonjs.com/#LFXT0L#1. I hope there is better solution for this.

I need to use PRBCustomMaterial. Then creating a custom attribute called myalpha. Make sure the attribute is passed from Vertex shader to Fragment shader. Then use the custom alpha hook in the PBRCustomMaterial to update the alpha.

 material.Fragment_Custom_Alpha(`alpha = vmyalpha.x;`);
1 Like

@slin that’s insane! Good but insane :slight_smile: I could use something like this, but then I would have a custom fragment shader to maintain, instead of what StandardMaterial provides out of the box (which is good enough for my use case). This makes me slightly hesitant… But thank you for this. If nobody comes up with something simpler, I will use it.

You can use a float as an instance value with a little trick:

https://playground.babylonjs.com/#LFXT0L#2

But that will do you no good because it won’t be used by the standard shader code.

What you can do instead is using the vertex color:

https://playground.babylonjs.com/#LFXT0L#4

4 Likes

@Evgeni_Popov

Wow. I didn’t know about this: copyToArray : (data, offset) => data[offset] = 0.4

Is it possible to pass instanced attributes that contain more than 4 floats. Like float arrary?

No, it seems passing an array of floats as attributes does not work. What you can do is using a texture instead and put your data there.

@Evgeni_Popov I realised that in my project I am actually instantiating a merged mesh with MultiMaterial. After applying your idea of using vertex color to imitate partial visibility, I achieved the effect, but also got some undesirable side effects. I reproduced this in https://playground.babylonjs.com/#LFXT0L#8

The instance of merged mesh, which consists of a red ball on a green rod, behaves odd when rotating around it. The green rod sometimes overlaps the red sphere.
visibility_of_instanced_mesh___Babylon_js_Playground

The problem disappears when I comment line 33 out

  mesh.hasVertexAlpha = true;

but then the transparency effect disappears as well.

This seems to be a known problem (see post), but this prevents me from using this approach. Unless perhaps you know a workaround to this problem? After all, the post comes from 5 years ago.

Unfortunately, I don’t think there’s a solution here because all the instances are drawn at once. So you will have either the spheres drawn first then the boxes, or the other way around. For a correct rendering, you would need each object to be drawn separately, something you won’t be able to do with instances (order of drawing with transparency is already a tough problem when no instances are involved).

@Evgeni_Popov that’s too bad. At least I can now understand better the limits of what instances can do and what not. Thank you for that

@Evgeni_Popov Setting transparency is not good enough in my opinion. Can we have a solution make instancedMesh not to be render instead of “isVisible = false” ? This makes we can control single instancedMesh display or not easier

I think InstancedMesh are already not displayed if isVisible=false?

1 Like

Correct!

Hi @DWork just checking in, do you have any further questions :slight_smile:

Hope the InstancedMesh has own property “visibility” :slightly_smiling_face:

Yeah, each individual instance has a isVisible property: Instances visibility | Babylon.js Playground (babylonjs.com)

2 Likes

You cannot set transparency on a single instance of a textured material. It seems invalid to use instancedBuffers.color for materials containing textures?

Take an example:

https://playground.babylonjs.com/#WGZLGJ#6828

If you set the instance to have the same parent as the mesh like below then it does work. @Evgeni_Popov would know better why thou, I just remember once he told me that it needed to be that way for instances to work properly, IIRC particularly with glb meshes because the parent has negative scaling? :slight_smile: EG it also works if you call setParent(null) on the mesh or if you change the root mesh’s z scaling from -1 to1.

OK Thank you, but I have a few questions to clarify. First, the transparency cannot be changed through instancedBuffers.color. How can we achieve.

let boomBoxInstance = BoomBox.createInstance('boomBoxInstance');
boomBoxInstance.instancedBuffers.color = new BABYLON.Vector4(1, 1, 1, 0.6);

Second, I need to wrap the object into a TransformNode. If a mesh has many child meshes, it is not feasible to use the same parent. They will have separate parents

For the second part, you can call setParent(null) on the mesh like below instead of using the same parent for them. But for the first part, IDK why the alpha channel of the color attribute isn’t having any effect. Only the rgb channels are, like below where I tinted it purple after nulling the mesh’s parent…

EDIT: PS I found the doc section here where it talks about gltf instancing for more info. :slight_smile:

1 Like

OK, thank you. How can I change the transparency (visibility) of gltf instances?