Three.js - Is Extra Mesh Material with Same Material Beneficial? - three.js

I am new to three.js. I know that you can combine multiple mesh materials into one mesh. What if the mesh is the same material? Would it add more detail? In otherwards, does the extra mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); do anything beneficial? By the naked eye it's hard for me to tell.
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
mesh = new THREE.Mesh( geometry, material );
mesh.position.z = - 1500;
scene.add( mesh );

It seems you have a bit of a mix-up in the terminology. A mesh is an actual object in a scene, where as a material describes mesh's properties, which influence its shading. So creating a second mesh and adding it to a scene would result in a second object with provided geometry and material (i.e. presentation). The probable reason you don't see it may be because it's to far along Z-axis and got culled by camera's far clipping plane (a.k.a Z far).
And to the "is it beneficial" part. It's implementation dependent, but it may be beneficial for rendering performance, because draw calls for meshes sharing a material (and hence shader program and its parameters) can be coalesced together without redundant state changes, which is always good in WebGL (and OpenGl, for that matter).

Related

fill bound issue, low fps in 360 scene with stacked transparent textures

I have a project with 360 scene - camera is inside the sphere and 360 photo is wrapped as texture around the sphere:
http://kitchen-360.herokuapp.com/
I added several smaller spheres with transparent textures and Im seeing sudden drop of performance. It is 'fill bound' issue as described in this link:
Debugging low FPS in Three.js
Im trying to solve this performance issue. Im thinking of having only one sphere with multiple textures on it. Is this gonna be faster then stacked spheres with one texture each?
I tried to create sphere mesh with array of MeshBasicMaterial but its not working. Only first texture in the array is visible:
// when texture is loaded I push it to array
var sphereMaterial = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
})
sphereMaterial.transparent = true;
matArr.push(sphereMaterial);
//... then later when all textures loaded
roomMesh = new THREE.Mesh( sphereGeometryR, matArr );
roomMesh.name = 'great room';
scene.add( roomMesh );
I saw this example for custom shader but dont know how to add and change textures dynamically at later time:
Multiple transparent textures on the same mesh face in Three.js
Is there any other way to optimize this problem? Would geometry merge help here?

Three.js / BufferGeometry how to use mesh & line material

I'm using BufferGeometry to draw triangles.
I can use a mesh geometry, specifiyng 3 index-attribute for every triangle. I'm using a basic material without wireframe. I suposse I'll can use raycast.
Also I have seen the linesegments approach for wireframe. Interesting.
Ok, my problem... I'd like to see my triangles as a wireframe and also I need raycast. So .... the solution is to create my own shader, isn't it ?
Thanks
you dont have to create a custom shader you can have a mesh with wireframe material, and the ray should still "hit" the object
var mesh = new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({wireframe : true}));
if it for some reason does not hit or you want to LineSegments object you can keep track of all transformations that affected the object, and apply them onto a mesh you wont add to scene
var segmentObject = new THREE.LineSegments(geometry,lineMaterial);
scene.add(segmentObject);
var meshNotInScene = new THREE.Mesh(geometry,dummyMaterial);
and you will use the mesh object to determine if raycast hit the object
this way you can have a different hitbox for an object for example if you have a flying donut by pairing it with a circle mesh you can select it even if you click in its hole etc...
keep in mind that materials have sides and if you dont care about which side is which set "side" to THREE.DoubleSide

three.js sizeAttenuation to Sprite material

I want the sprite in the scene don't change the size when the camera zoom in or out. and the sprites use different canvas texture as the material.
I found that the sizeAttenuation in ParticleBasicMatierial can work for me. But if I use the WenGLRenderer, I must use ParticleSystem instead of the Particle with the CanvasRenderer.
I currently use ParticleSystem to contain only one vertex, and every vertex correspond to one ParticleSystem, so there are about 800+ ParticleSystem in my scene, this can work, but consume a lot.
Obviously, I can't use "HUD" as the example in three.js source, because the sprites are all in 3D scene.
Can some one help me. Or add the sizeAttenuation to Sprite Material! Thanks!
If you want to prevent size attenuation with sprites, and you are using a perspective camera, you can set the sizeAttenuation property of your material to false:
var material = new THREE.SpriteMaterial( {
color: 0xffffff,
map: texture,
sizeAttenuation: false
} );
This feature was added in three.js r.96.
EDIT: Updated to three.js r.96

THREE.js flickering with pointlight and MeshFaceMaterial

For some reason I am getting flicker on any objects with using MeshFaceMaterial while I have a pointlight in the scene. Ambient and Directional lights are fine.
This is unfortunate, the pointlight adds an extra level of realism to the scene. If I remove the pointlight all is well. Pseudo code:
light = new THERE.PointLight(0xffffff,0.5);
scene.add(light);
loadTerrain();
mesh = new THREE.Mesh(cominedGeometry,new THREE.MeshFaceMaterial(materialArray))
scene.add(mesh);
I've tried loading the light before and after all other objects have loaded, no change in the flickering.
Why is there flickering under these conditions? Is there any remedy for this?

Specular highlights with a model imported from Blender?

I made in Dice with 2 different colored materials in Blender and exported it with the Blender exporter. In my three.js code, I use JSONLoader to get the mesh and use new THREE.MeshFaceMaterial(); as material.
This loads the model just fine with the two different colored materials showing correctly. But my problem is, that I want the dice to have specular highlights on the surface. Is this even possible with exported Blender models?
I managed to get a Sphere with specular highlights when I used THREE.MeshPhongMaterial() as material for the sphere, but the sphere wasn't imported from Blender and as far as I know, I can't apply a Phong Material when I load the Mesh with JSONLoader, or is there a trick? Please remember: I got two differently colored materials on the dice, which I import from Blender in the JSON file. The dice by itself is red, but the dots should be black. So I am not talking about different colors on each side of a cube or so, but two different colors on every side of the cube. Can you help me?
Here's the code snippet:
loader.load("models/dice.js", function(geometry){
var material = new THREE.MeshFaceMaterial();
material.specular = 0xffffff;
material.shininess = 10000000000;
dice=new THREE.Mesh(geometry, material);
dice.position.set(0,-400,5);
dice.scale.set(75, 75, 75);
dice.overdraw = true;
dice.name="dice";
navscene.add(dice);
});
If it helps, I am able to create a texture out of the two materials and apply them in Blender, so that the JSONLoader loads the texture instead of the materials, but I wasn't able to achieve a specular highlight either with that.
Thx West, you pointed me into the right direction. The problem was, that Blender's standard material type is Lambert. In Blender, this Lambert material produces the desired specular highlight, but once imported to three, the effect is gone. I don't know if this is a bug, or a desired behaviour.
The solution is to set the material type in Blender to Phong material. This works even after import. My guess is, that THREE.MeshFaceMaterial is an array which contains all the loaded materials, whether they are lambert, phong or whatever. It is even possible to mix those material types. So it appears to me, that THREE.MeshFaceMaterial doesn't seem to be a "stand alone" material type at all. Correct me if I'm wrong please.
If your mesh geometry has a materials array, you can always change the array elements after you load the geometry:
geometry.materials[ i ] = new THREE.MeshPhongMaterial( ... );
You then leave the mesh's material as MeshFaceMaterial:
mesh = new THREE.mesh( geometry, new THREE.MeshFaceMaterial() );
The exporter script you are using may set geometry.materials to Lambert material by default, based on your settings. Have a look at the script source code and see if you can figure it out.

Resources