I want to make parts of a mesh invisible at runtime. Can I set these parts invisible/transparent, e.g. by changing attributes of single faces? The mesh itself uses only one material.
Exemplary illustration as the editor understands this question: Imagine a mesh (here with a geometry of 20 vertices) where each quad of four vertices builds up a Face4. Now, some parts of the mesh should be made invisible (here two faces are invisible).
Note: This answer applies to legacy versions of three.js
You can assign a different material to each face. Here is an example where the faces share a material, but some faces are transparent:
// geometry
var geometry = new THREE.BoxGeometry( 100, 100, 100, 4, 4, 4 );
// materials
materials = [
new THREE.MeshLambertMaterial( { color: 0xffff00, side: THREE.DoubleSide } ),
new THREE.MeshBasicMaterial( { transparent: true, opacity: 0 } )
];
// assign material to each face
for( var i = 0; i < geometry.faces.length; i++ ) {
geometry.faces[ i ].materialIndex = THREE.Math.randInt( 0, 1 );
}
geometry.sortFacesByMaterialIndex(); // optional, to reduce draw calls
// mesh
mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
three.js r.87
Related
I'm working on a problem with three.js and ExtrudeGeometry.
I do have a wave-like structure which is made from several individual frames. Each of them is extruded using ExtrudeGeometry.
I'd like to apply a texture to each frame of the structure which is "wrapped around" the structure. For some reason (possibly wrong UV-mapping?) the texture does not display correctly on the extruded edges where the wave-like surface is out of level. (There are some tiny sections in the picture where the texture wraps correctly). I'm using the following script to apply the textures:
// create some simple Geometry
var shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0,10 );
shape.lineTo( 100,7 );
shape.lineTo( 100,0 );
var extrudeSettings = {
steps: 2,
amount: 10,
bevelEnabled: false,
bevelThickness: 0,
bevelSize: 0,
bevelSegments: 0
};
var geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
var texture = new THREE.Texture( image );
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
texture.repeat.set( 0.1, 0.1 );
var material = new THREE.MeshBasicMaterial( {map: texture} );
var mesh = new THREE.Mesh( geometry, material ) ;
scene.add( mesh );
Every help is much appreciated! Cheers!
Edit:
I've created this image to better illustrate the problem. White Arrows show, how the texture is supposed to wrap around the object. At some very rare spots it actually does!
Have a look at this example
https://threejs.org/examples/?q=geome#webgl_geometry_shapes
at row 70 there is a comment that states that texture.repeat must be set to (0.008, 0.008)
I would to apply a transparent material on front-side faces of a geometry. It's quite easy:
var normal = new THREE.MeshNormalMaterial();
normal.side = THREE.BackSide;
var materials = [
normal,
new THREE.MeshBasicMaterial( { transparent: true, opacity: 0 } )
];
for( var i = 0; i < geometry.faces.length; i++ ) {
geometry.faces[ i ].materialIndex = 0;
}
//a 'hole' to look inside
geometry.faces[ 0 ].materialIndex = 1;
geometry.faces[ 1 ].materialIndex = 1;
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
Codepen to example above: http://codepen.io/pyort/pen/egqbLY
But there is a catch: when looking on a front-side of a face, I would like to show what's underneath this geometry, not back-side.
I'm not sure how to explain that in easy language, here is visual explanation
What is my goal is this kind of 'portal' thing, so when you look from one side, it appears to have depth, but from other angles it's look super thin. How to achieve such an effect? Use some kind of shader? Use mirror techniques?
Thanks.
Try something like this:
// the inside of the hole
let geometry1 = new THREE.CubeGeometry(2,2,2);
let material1 = new THREE.MeshLambertMaterial({
transparent : true,
color: 0xff0000,
side: THREE.BackSide
});
mesh1 = new THREE.Mesh( geometry1, material1 );
scene.add( mesh1 );
// the invisibility cloak (box with a hole)
let geometry0 = new THREE.BoxGeometry(2,2,2);
geometry0.faces.splice(4, 2); // make hole by removing top two triangles
let material0 = new THREE.MeshBasicMaterial({
colorWrite: false
});
let mesh0 = new THREE.Mesh( geometry0, material0 );
mesh0.scale.set(1,1,1).multiplyScalar(1.01); // slightly larger than inside cube
scene.add(mesh0);
Live examples are at https://stemkoski.github.io/AR-Examples/
In a three.js scene, I would like to have an object that's not visible, but still occludes other objects in the scene as if it was visible.
Is this possible with the three.js library? Here is an example:
Suppose I have a three.js scene that contains 3 objects: object a, object b and object c and a camera. I would like object c to be invisible to the camera, but still occlude object b... Scenario 1:
In scenario 1, here is what I would like the camera to see:
Scenario 2:
In scenario 2, here is what I would like the camera to see:
Can anyone tell suggest a technique use to achieve such an effect?
Yes, in three.js you can create an object that is invisible, but still occludes other objects as if it were visible.
To do that, you need to use two features available in three.js: Object3D.renderOrder and Material.colorWrite.
You need to make sure the invisible object is rendered prior to the object(s) it must occlude.
You control the rendering order with the renderOrder property.
You make the occluding object invisible by setting its material's colorWrite property to false.
// material
var material = new THREE.MeshPhongMaterial();
// mesh a
var geometry = new THREE.PlaneGeometry( 10, 10, 4, 4 );
mesh = new THREE.Mesh( geometry, material.clone() );
mesh.material.color.set( 0xff0000 );
mesh.renderOrder = 0; // <===================
mesh.position.z = - 10;
scene.add( mesh );
// mesh b
var geometry = new THREE.BoxGeometry( 2, 2, 2 );
mesh = new THREE.Mesh( geometry, material.clone() );
mesh.material.color.set( 0x606060 );
mesh.renderOrder = 3;
mesh.position.z = 0;
scene.add( mesh );
// mesh c
var geometry = new THREE.BoxGeometry( 3, 3, 3 );
mesh = new THREE.Mesh( geometry, material.clone() );
mesh.material.color.set( 0x0000ff );
mesh.material.colorWrite = false; // <=================
mesh.renderOrder = 2;
mesh.position.z = 10;
scene.add( mesh );
three.js r.143
Is it possible to load multiple textures on a sphere?
I mean to say is there any way in Three.js to split a sphere into n pieces , texture them separately and render those pieces once again as a whole sphere?
I do not want to load the entire texture on the sphere, instead, only those parts are to be rendered which the user will first see on the screen and as the user rotates the sphere the rest part of the texture must be loaded.
Moreover, when I use a single image on a sphere it seems to converge at poles making it worse.
This should help: https://open.bekk.no/procedural-planet-in-webgl-and-three-js
Instead of using a sphere try using a cube and expanding it into a sphere. Cube logic on the cube sphere will save you a good amount of time.
var geometry = new THREE.BoxGeometry( 1, 1, 1, 8, 8, 8 );
for ( var i in geometry.vertices ) {
var vertex = geometry.vertices[ i ];
vertex.normalize().multiplyScalar(radius);
}
var materialArray = [];
var faceMaterial = new THREE.MeshLambertMaterial({
color: sphereColor,
transparent: true,
opacity: 0.4
});
for (var i = 0; i < 6; i++) {
materialArray.push(faceMaterial);
}
var material = new THREE.MeshFaceMaterial(materialArray);
var sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
I'm trying to draw a wireframe mesh and a textured mesh in threeJS but when I have both added to my scene the textured mesh doesn't display. Code below:
I'm having trouble creating two meshes that share the same geometry where one of the materials is wireframe and the other is a texture. If one of the materials is wireframe and the other is just a color fill it works fine- but as soon as I make the second material a texture it stops working.
If I comment out scene.add( wireMesh ); then the textured mesh shows up.
var wireMat = new THREE.MeshBasicMaterial( { color:0x00FFFF, wireframe: true, transparent: true, overdraw:true } );
var wireMesh = new THREE.Mesh(geometry, wireMat);
scene.add( wireMesh );
var texture = texture = THREE.ImageUtils.loadTexture( 'textures/world.jpg' );
var imageMat = new THREE.MeshBasicMaterial( {color:0xffffff, map: texture } );
var fillMesh = new THREE.Mesh(geometry, imageMat);
scene.add( fillMesh );
Under SceneUtils there is a createMultiMaterialObject(geometry, materials). It essentially creates multiple meshes that all share the same geometry all in a group.
Example:
var mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [
new THREE.MeshLambertMaterial( { color: 0xffffff} ),
new THREE.MeshBasicMaterial( { color: 0x222222, wireframe: true} )
]);
THREE.SceneUtils source code
Unfortunately it is not possible to share geometry between an object using wireframe and another one not using it. You'd need to clone that geometry. Which reminds me that we haven't done .clone() for Geometry yet.