I have a BufferGeometry object and I want to be able to assign a different texture to each face.
In my example here: https://jsfiddle.net/2ay716mz/ (working example)
I have setup a cube (using custom BufferGeometry not BoxGeometry seeing as I need other objects that are not cubes).
I have passed an array of materials to the mesh, one side is a texture and the other sides are all different colors.
This all works correctly...however if I try to put the texture material on any face group , other than the group[0] and group[1], then it doesn't work and just shows a color instead.
See in this example where I have set the texture to be the third material; it no longer works: https://jsfiddle.net/2ay716mz/1/
How can I solve this? Or is this a bug and should be reported to three.js github?
It works fine on my end. You just have to assign a new material to each texture you want to use:
const texLoader = new THREE.TextureLoader();
const texURL1 = 'https://upload.wikimedia.org/wikipedia/commons/9/93/Gfp-jagged-rock-texture.jpg';
const texURL2 = 'https://threejs.org/examples/textures/patterns/circuit_pattern.png';
const texURL3 = 'https://threejs.org/examples/textures/decal/decal-normal.jpg';
const texURL4 = 'https://threejs.org/examples/models/gltf/LeePerrySmith/Map-COL.jpg';
const texURL5 = 'https://threejs.org/examples/models/gltf/LeePerrySmith/Map-SPEC.jpg';
const texURL6 = 'https://threejs.org/examples/textures/cube/pisa/px.png';
const mat1 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL1)});
const mat2 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL2)});
const mat3 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL3)});
const mat4 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL4)});
const mat5 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL5)});
const mat6 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL6)});
var material = [
mat1,
mat2,
mat3,
mat4,
mat5,
mat6,
];
Click here for live demo
Related
Im working with Three.js particles , and trying to map multiple png textures, (my png images are juste différent colors stars to create a sky full of stars)
my code looks like this :
const loader = new THREE.TextureLoader();
const cross = loader.load ('./cross1.png');
const cross2 = loader.load ('./cross3.png');
.
.
.
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross,
transparent: true
})
// Mesh
const sphere = new THREE.Points(geometry,material)
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial)
scene.add(sphere, particlesMesh)
it works fine with only maping one elmement "cross" .
my question is, how can i MAP multiple images to get like a random mix please ?
something like :
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross, cross2, cross3
transparent: true
})
THANKS !
If you are looking to make stars with multiple colors I would just create 3 instances of points mesh with each one containing their respective textures.
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross,
transparent: true
})
const particlesMaterial2 = new THREE.PointsMaterial({
size: 0.02,
map: cross2,
transparent: true
})
const particlesMaterial3 = new THREE.PointsMaterial({
size: 0.02,
map: cross3,
transparent: true
})
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial)
const particlesMesh2 = new THREE.Points(particlesGeometry, particlesMaterial2)
const particlesMesh3 = new THREE.Points(particlesGeometry, particlesMaterial3)
scene.add(particlesMesh, particlesMesh2, particlesMesh3)
this works as long as your point coordinates are randomized
I am trying to add a mesh into the Forge viewer using Three.js. I used the same code and I was able to add the plane in windows but not in Linux.
The minimum code to replicate the problem is below.
const drawingMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00 } );
const planeGeometry = new THREE.PlaneBufferGeometry(400, 200);
const texturePlane = new THREE.Mesh( planeGeometry, drawingMaterial);
texturePlane.material.side = THREE.DoubleSide;
texturePlane.position.z = 0
this.viewer.impl.sceneAfter.add(texturePlane);
I'm trying to offset a texture that's being used as an environment map, but not having much luck.
The texture is loaded with the loadTextureCube() method, which gets applied to my mesh just fine, but the offsets don't seem to have any effect.
The texture is just a big gray circle to give a little bit of gloss.
Any thoughts on what I'm doing wrong?
var urls = [
'pos-x.png',
'neg-x.png',
'pos-y.png',
'neg-y.png',
'pos-z.png',
'neg-z.png'
];
var cubemap = THREE.ImageUtils.loadTextureCube(urls);
cubemap.offset.y = -.5;
cubemap.offset.x = -.5;
cubemap.needsUpdate=true;
I'm assuming based on loadTextureCube that your utilizing the cube shader approach to skyboxes. So far everything with your code is fine. The problem your seeing is that while your texture has offset properties, the material (or more specifically the cube shader program therein) does not have uniforms to pass this along to the fragmentation shader. This of course is assuming your doing something like this:
Eg. cube shader material
var skyboxGeo = new THREE.CubeGeometry( 5000, 5000, 5000 );
var cubeShader = THREE.ShaderUtils.lib[ "cube" ];
cubeShader.uniforms[ "tCube" ].value = cubemap;
var skyboxMat = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
side: THREE.BackSide
});
var skybox = new THREE.Mesh( skyboxGeo, skyboxMat );
scene.add( skybox );
There's likely a number of work arounds, but you could alway try something like a MeshFaceMaterial on a standard cube to achieve the desired result:
Eg. standard material
var skyboxGeo = new THREE.CubeGeometry( 5000, 5000, 5000 );
var materialArray = [];
for (var i = 0; i < 6; i++) {
var cubeTex = THREE.ImageUtils.loadTexture( urls[i] );
cubeTex.offset.x = -.5;
cubeTex.offset.y = -.5;
materialArray.push( new THREE.MeshBasicMaterial({
map: cubeTex,
side: THREE.BackSide
}));
}
var skyboxMat = new THREE.MeshFaceMaterial( materialArray );
var skyBox = new THREE.Mesh( skyboxGeo, skyboxMat );
Hope that helps
~D
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 ));
How to invert a mesh using three.js
I had a mesh created using THREE.Mesh
var geometry = new THREE.ExtrudeGeometry( featurePts,extrudeSettings);
var mat = new THREE.MeshBasicMaterial( { color: color, wireframe: true, transparent: true } );
var mesh = new THREE.Mesh(geometry, mat );
But my shape looks inverted. Is there any way in Three.js to invert my shape?
shape used above is a list of THREE.Vector2
var featurePts = [];
featurePts.push(new THREE.Vector2 (550,107));
If you mean it looks inside out, try reversing your normals.