Different material on back and frontside of extruded shape - three.js

I'm trying to apply different material on front and back sides of extruded shape, but cannot figure out where to put side: THREE.FrontSide and side: THREE.BackSide. Where they should be putted?
My relevant code part is:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture });
var materialSide = new THREE.MeshPhongMaterial({color: 0xE68A00, ambient: 0xffffff});
var extrusionSettings = {
amount: 10,
bevelEnabled: false,
bevelThickness: 0.2,
bevelSize: 0.2,
bevelSegments: 8,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shapes, extrusionSettings);
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
UPDATE:
According to WestLangley's comment I succeeded in adding the different texture to backfaces:
// ...
var materials = [materialFront, materialSide, materialBack];
// ...
for ( var face in mesh.geometry.faces ) {
if (mesh.geometry.faces[ face ].normal.z == 1) mesh.geometry.faces[ face ].materialIndex = 2;
}

After you create your mesh geometry, and before the first call to render(), you have to change the materialIndex to 2 for the back faces. Then, add a third material in your material array.
You can identify the back faces by their face normals. Face normals for faces on the back of the geometry should all point in the same direction.
three.js r.58

Try using:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture, side: THREE.FrontSide });
var materialSide = new THREE.MeshPhongMaterial({ color: 0xE68A00, ambient: 0xffffff, side: THREE.BackSide });
even though you should probably lower your ambient contribution and give a color to the FrontSide material.
Then:
var materials = [materialFront, materialSide];
scene.add( THREE.SceneUtils.createMultiMaterialObject( geometry, materials ));

Related

MeshPhongMaterial or MeshStandardMaterial does not give me the expected output with metallic look

I have the following lights, the ambient light and one PointLight attached to the camera.
this.ambientLight = new THREE.AmbientLight(0xffffff, 0.9);
var pointLight = new THREE.PointLight(0xffffff, 1);
//add to the camera/scene
this.camera.add(pointLight);
this.scene.add(this.ambientLight);
And I'm using the following meshes that I'm trying to give a metallic look, a sphere and a custom mesh that appears like a beam (here the code is simplified)!
//sphere
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10, 10, 10), material2);
//custom mesh
const shape = new THREE.Shape();
shape.moveTo(0,0);
shape.lineTo(0,1);
shape.lineTo(1,1);
shape.lineTo(1,0);
shape.lineTo(0,0);
const extrudeSettings = {
steps: width, // ui: steps
depth: width, // ui: depth
};
var geom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
var beam = new THREE.Mesh(geom , material);
And I've tested with the following materials:
const material = new THREE.MeshPhongMaterial(
{
flatShading: true,
emissive: 'grey',
color: 'grey',
shininess: 150,
side: THREE.DoubleSide,
});
const material2 = new THREE.MeshStandardMaterial({
metalness: 1,
emissive: 'grey',
color: 'grey',
side: THREE.DoubleSide,
flatShading: true,
});
I've tried messing around with the materials settings, but no luck! I want to obtain a metal finishing look, with shadows/depth, ideally using the MeshPhongMaterial!
At the moment, it looks like this:
Am I doing anything wrong with the lightning or with the materials?

Layer multiple materials onto SphereGeometry in three.js

I'm attempting to create a sphere in three.js with a base material and a transparent png material over the top. I found this answer helpful in understanding how to load multiple materials. However when I try to apply this to SphereGeometry rather than BoxGeometry as in the example, only the second material is visible, with no transparency.
http://jsfiddle.net/oyamg8n3/1/
// geometry
var geometry = new THREE.BoxBufferGeometry( 10, 10, 10 );
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
geometry.addGroup( 0, Infinity, 2 );
geometry.addGroup( 0, Infinity, 3 );
// textures
var loader = new THREE.TextureLoader();
var splodge = loader.load( 'https://threejs.org/examples/textures/decal/decal-diffuse.png', render );
var cat = loader.load('https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80.jpeg', render)
// materials
var catMat = new THREE.MeshPhongMaterial( {
map: cat,
} );
var splodgeMat = new THREE.MeshPhongMaterial( {
map: splodge,
alphaTest: 0.5,
} );
var materials = [ catMat, splodgeMat ];
// mesh
mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
Can I use these same principles for
var geometry = new THREE.SphereGeometry( 5, 20, 20 );
It does work if you use SphereBufferGeometry and not SphereGeometry. Notice that both classes have a different super class. You want to work with the BufferGeometry version.
Demo: http://jsfiddle.net/r6j8otz9/
three R105

Multiple mateials with pointcloudmaterial and linebasicmaterial

i like to draw a line with two vertices[10,10,0][-10,-10,0]. i can create a line sucessfully,
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector(10,10,0));
geometry.vertices.push(new THREE.Vector(-10,-10,0));
geometry.verticesNeedUpdate = true;
var material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 2, side: 2 });
var line = new THREE.Line(geometry, material);
scene.add(line);
I like to draw two particle on the vertices of the line,
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector(10,10,0));
geometry.vertices.push(new THREE.Vector(-10,-10,0));
geometry.verticesNeedUpdate = true;
var material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 2, side: 2 });
var material1 = new THREE.PointCloudMaterial({ color: 0xff0000, size: 3, sizeAttenuation: false });
var materials = new THREE.MeshFaceMaterial([material, material1]);
var line = new THREE.Mesh(geometry, materials);
scene.add(line);
this method not working, mesh created but not visible in scene.
can any one give some good suggestion on it..
AFAIK a mesh would need atleast 3 vertices to create a face in a mesh. take a look at the Line class docs for how to create a line.
eg.
var line = new THREE.Line( geometry, material )

Repeating texture of the PlaneGeometry

The way of reproduction of the texture, independent of the extent of object is necessary to me. If, for example, to do:
var geometry = new THREE.PlaneGeometry( 400, 400, 10, 10 );
var Texture = THREE.ImageUtils.loadTexture( 'textures/texture.png' );
Texture.wrapS = Texture.wrapT = THREE.RepeatWrapping;
Texture.repeat.set( 2, 1 );
var material = new THREE.MeshBasicMaterial({
map: Texture,
side: THREE.DoubleSide,
});
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(-400,0,0);
scene.add( mesh );
var mesh = new THREE.Mesh( geometry.clone(), material.clone() );
mesh.scale.x = 2;
mesh.position.set(400,0,0);
scene.add( mesh );
result here
How to redefine texture to receive the following result?
here

Using multiple materials with THREE.CylinderGeometry - create a wheel from cylinder

I want to create a wheel from cylinder (because importing 3D models makes it slower). But I cannot use multiple materials with cylinder geometry. It uses only the first material in an array.
var geometry = new THREE.CylinderGeometry(this.diameterWheel/2,this.diameterWheel/2,this.lastikGenisligi, 20, 4);
var materialArray = [];
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x000000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( '../textures/wheel.png' ) }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x0000FF }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0xFF0000 }));
var material = new THREE.MeshFaceMaterial(materialArray);
var mesh = new THREE.Mesh(geometry, material);
What I want to create is a wheel which will have wheel.png wheel image on upper and bottom sides and black coverage on between them.
You need to loop through each face on the cylinder and tell which of the array materials the face uses.
geometry.faces[a].materialIndex = b;
Where a is the face index. You need to figure out yourself which face is which to choose the correct material through some system, ie. faces 0-10 with one color, etc. This depends on the cylindergeometry parameters. And b is the material index.

Resources