Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Many meshes with the same geometry and material, can I change their colors?

I have a large number (~1000) of THREE.Mesh objects that have been constructed from the same THREE.Geometry and THREE.MeshPhongMaterial (which has a map).

I would like to tint (color) these objects individually.

Naïvely, I tried changing the mesh.material.color property, but changing this property on any of the objects changes the color of all the objects at once. This makes sense, since there is only one material that is shared among all the objects.

My next idea was to create a separate THREE.MeshPhongMaterial for each object. So, now I have a large number of THREE.Mesh objects that been constructed from the same THREE.Geometry, but have individual THREE.MeshPhongMaterials (that share the same texture). This allows me to change the colors individually, but the performance is worse. The chrome profilier shows that the app is spending significant time doing material-things like switching textures.

The material color is just a uniform in the shader. So, updating that uniform should be quite quick.

question: Is there a way to override a material color from the mesh level?

If there was, I believe I could share the material among all my objects and get my performance back, while still changing the colors individually.

[I have tested on v49 and v54, they have identical performance and degredation]

update: I have built a test case, and the performance drop due to this is smaller than I thought it was, but is still measurable.

Here are two links:

  • http://danceliquid.com/docs/threejs/material-test/index.html?many-materials=false
  • http://danceliquid.com/docs/threejs/material-test/index.html?many-materials=true

In the first case, there are only two materials, in the second case each cube has it's own material. I measure the framerate of the first case to be 53fps on this machine, and the framerate of the second is 46fps. This is about a 15% drop.

In both cases, the color of the material of every cube is changed every frame. In the case with many materials, we actually see each cube getting it's own color, in the case with only two materials, we see them all having the same color (as expected).

like image 230
Harold Avatar asked Jan 03 '13 18:01

Harold


1 Answers

Yes. Per object, clone your material using material.clone(), modify its emissive and color, and set the object's material to this clone. Shaders and attributes are copied by reference, so do not worry that you are cloning the entire material each time; in fact the only things that are copied by value are the uniforms (such as emissive and color). So you can change these per individual object.

Personally I store the original material on a separate, custom property of the object so that I can easily switch back to it later; depends what your needs are.

like image 131
Engineer Avatar answered Nov 02 '22 10:11

Engineer