I've recently started to play with three.js, and I am using terrain.js demo as a start for a design project I am working on.
I will like to add a hybrid shader "wireframe/lambert"
the default comes with wire shader only.
This is the code from the demo, using basic material:
var matrix = new THREE.MeshBasicMaterial({
color:0x10ce58,
wireframe:true
});
var geometry = new THREE.PlaneGeometry(width, height, modelWidth, modelHeight);
mesh = new THREE.Mesh(geometry, matrix);
mesh.doubleSided = false;
and I tried something like this but I only get the "lambert" rendering and not the lambert and wire combined, any ideas?
var darkMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff , shading: THREE.FlatShading, overdraw: true} );
var wireframeMaterial = new THREE.MeshBasicMaterial( { color: 0x10ce58, wireframe: true, transparent: true } );
var multiMaterial = [ darkMaterial, wireframeMaterial ];
var geometry = new THREE.PlaneGeometry(width, height, modelWidth, modelHeight);
mesh = new THREE.Mesh(geometry, multiMaterial);
mesh.doubleSided = false;
Thanks for your time in advanced,
Regards
-Manuel
This is the code I am using in my non working example for materials (http://jsfiddle.net/xnqUb/3/)
var geometry = new THREE.PlaneGeometry(width, height, model.length - 1, model.length - 1, materials);
materials = [
new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ),
new THREE.MeshLambertMaterial({ color: 0x10ce58, wireframe: true,})
];
var mesh = new THREE.Mesh(geometry);
object = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
Related
I am trying to add some text on a cylinder geometry ...I tried to map texture which is working but when I try to add text it doesn't work
I just want to map text (like texture) on the outer side of the cylinder geometry in such a way that if the shape changes, the text follows the shape and look like engraved on the surface
var geometry = new THREE.CylinderGeometry(2.5, 2.5, 5, 10000, 1, true, 100);
var materialOuter = new THREE.MeshLambertMaterial({
color: 0x581845
});
var materialOuter = new THREE.MeshBasicMaterial({
// map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/758px-Canestra_di_frutta_(Caravaggio).jpg")
map: new THREE.FontLoader().load('/fonts/gentilis_regular.typeface.json', function (font) {
var textGeo = new THREE.TextGeometry("My Text", {
font: font,
size: 200,
height: 50,
curveSegments: 12,
bevelThickness: 2,
bevelSize: 5,
bevelEnabled: true
});
var textMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var mesh = new THREE.Mesh(textGeo, textMaterial);
// mesh.position.set(x, y, z);
// scene.add(mesh);
})
});
var materialInner = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("../images/1.jpg"),
side: THREE.BackSide
});
var materialInner = new THREE.MeshLambertMaterial({ color: 0xd2691e, side: THREE.BackSide });
var meshOuter = new THREE.Mesh(geometry, materialOuter);
var meshInner = new THREE.Mesh(geometry, materialInner);
meshOuter.add(meshInner);
var bottomCylinder = new THREE.Mesh(new THREE.CylinderGeometry(2.5, 2.5, 0.01, 10000, 1, false, 100), new THREE.MeshLambertMaterial({ color: 0xFFC300, wireframe: false, shading: THREE.FlatShading }));
bottomCylinder.position.y = -2.5;
scene.add(bottomCylinder);
scene.add(meshOuter);
var light = new THREE.AmbientLight(0xffffff);
light.position.z = 200;
scene.add(light);
I'm trying to create the effect similar to hula hoop covered in tape using three.js.
The 3d model should end up looking something like below.
I can create the hoop in 3d space using TorusGeometry with the ability to pan around, but I have not managed to work out how to get a 2nd TorusGeometry to break into sections.
What is the best way of creating this effect?
// hoop
hoop = new THREE.TorusGeometry(20, .5, 100, 50);
var hoopMaterial = new THREE.MeshPhongMaterial({
ambient: 0xffffff,
color: 0x028fde,
specular: 0x555555,
shininess: 0
});
hoopMesh = new THREE.Mesh(hoop, hoopMaterial);
hoopMesh.position.z = 0;
scene.add(hoopMesh);
hoopTape1 = new THREE.TorusGeometry(20.1, .6, 0, 50);
var hoopTapeMaterial = new THREE.MeshPhongMaterial({
ambient: 0xffffff,
color: 0xDE5102,
specular: 0x555555,
shininess: 0
});
hoopTape1Mesh = new THREE.Mesh(hoopTape1, hoopTapeMaterial);
hoopMesh.position.z = 0;
scene.add(hoopTape1Mesh);
jsfiddle with current working code.
You will have to apply a texture to your torus that is seamless to achieve that effect. The texture should be similar to this one:
Then use this code pattern:
var geometry = new THREE.TorusBufferGeometry( 6, 0.4, 16, 64 );
var loader = new THREE.TextureLoader();
var texture = loader.load( 'stripe.jpg', function ( texture ) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 16, 0.5 ); // or whatever you like
render();
} );
var material = new THREE.MeshPhongMaterial( {
color: 0x998877,
specular: 0x050505,
shininess: 50,
map: texture
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
three.js r.77
I use Blender in combination with the exporters from Three.js
and spit it out in JSON. I like to apply a texture on a object but it seems not to work. What am I doing wrong?
var feinleinenMap = THREE.ImageUtils.loadTexture('textures/feinleinen.jpg');
feinleinenMap.anisotropy = 16;
feinleinenMap.wrapS = feinleinenMap.wrapT = THREE.RepeatWrapping;
feinleinenMap.repeat.set(5, 5);
var feinleinen = {
"schwarz": new THREE.MeshPhongMaterial({
color: 0x222222,
map: feinleinenMap,
combine: THREE.MixOperation
}),
"weiss": new THREE.MeshPhongMaterial({
color: 0xffffff,
map: feinleinenMap,
combine: THREE.MixOperation
}),
"chamois": new THREE.MeshPhongMaterial({
color: 0xEDE6D4,
map: feinleinenMap,
combine: THREE.MixOperation
}),
}
var group = new THREE.Group();
loader.load('/models/dagobert/basis.js', function (geometry) {
var mesh = new THREE.Mesh(geometry, feinleinen["schwarz"]);
loadJson(mesh);
});
function loadJson(mesh) {
group.add(mesh);
}
scene.add(group);
You need to run your scene through a server, else the texture wont load.
http://www.wampserver.com/en/ PC
https://www.mamp.info/en/ mac
Or use Brackets live preview and it should work for you.
r65
Hello,
I need to switch from simple material to multi-material on runtime. But can't. May be I miss something obvious?
My test code is below (jsfiddle: http://jsfiddle.net/plotnik/8RtTy/3/). Simple material is assigned to object initially, multi-material is assigned after the render() call to simulate runtime substitution.
var geom = new THREE.CubeGeometry(1, 1, 1);
var materialSimple = new THREE.MeshLambertMaterial({color: 0x020202});
// 6-color
var materialMulti = new THREE.MeshFaceMaterial([
new THREE.MeshLambertMaterial( { color: 0xff0000 }),
new THREE.MeshLambertMaterial( { color: 0xffff00 }),
new THREE.MeshLambertMaterial( { color: 0xffffff }),
new THREE.MeshLambertMaterial( { color: 0x00ffff }),
new THREE.MeshLambertMaterial( { color: 0x0000ff }),
new THREE.MeshLambertMaterial( { color: 0x000000 })
]);
var mesh = new THREE.Mesh(geom, materialSimple);
scene.add(mesh);
var render = function () {
requestAnimationFrame(render);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
// switch to multi-material
mesh.material = materialMulti;
mesh.material.needsUpdate = true;
The code doesn't work as I expect. The result looks like only materialMulti[0] (of red color) is assigned to the whole mesh.
I will be grateful for the assistance.
Switching materials at runtime can be tricky with WebGLRenderer. You can read more about it in the Wiki article How to Update Things with WebGLRenderer.
In you case, you can just use MeshFaceMaterial all the time, and achieve the effect you want by changing only the material colors.
EDIT: MeshFaceMaterial has been deprecated. You can now pass in an array of materials directly to the Mesh constructor`like so:
var mesh = new THREE.Mesh( geometry, materials_array );
three.js r.91
I created a cube using the canvas renderer with r59 of Three.js. The cube has different textures on different sides. This renders okay. I can also TWEEN this cube's position and rotation, so it's fine.
Here's what I want to do:
A) The cube has an image texture on it's front side.
B) I move this cube out of the camera's view.
C) I change the image texture on the cube.
D) I move the cube back to its original coordinates so it becomes visible again.
So far, steps A, B and D are working. But when I try to implement step C, it stops working.
Here are the relevant code parts...
<body>
<script src="build/three.min.js"></script>
<script src="js/libs/tween.min.js"></script>
<script>
var container;
var camera, scene, renderer, group, particle;
var cubeMesh;
var MatCollection = [];
var Materials = [];
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 1000;
scene = new THREE.Scene();
var cubeGeometry = new THREE.CubeGeometry(800, 600, 30, 8, 8, 8);
cubeGeometry.dynamic = true;
// creating three textures
var neheTextureSMALL = new THREE.ImageUtils.loadTexture("test3.jpg");
var neheTextureBIG1 = new THREE.ImageUtils.loadTexture("break01.jpg");
var neheTextureBIG2 = new THREE.ImageUtils.loadTexture("break02.jpg");
// putting two different sets of Materials to a material collection array
Materials = [
new THREE.MeshBasicMaterial({
map:neheTextureBIG1,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureBIG1,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureBIG1,
side: THREE.DoubleSide
})
];
MatCollection.push( Materials );
Materials = [
new THREE.MeshBasicMaterial({
map:neheTextureBIG2,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureSMALL,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureBIG2,
side: THREE.DoubleSide
}),
new THREE.MeshBasicMaterial({
map:neheTextureBIG2,
side: THREE.DoubleSide
})
];
MatCollection.push( Materials );
cubeMesh = new THREE.Mesh(cubeGeometry, new THREE.MeshFaceMaterial( MatCollection[0] ));
cubeMesh.dynamic = true;
cubeMesh.position.set(0, 0, 500);
// Applying the first set of materials on cubeMesh creation works good
renderer = new THREE.CanvasRenderer();
renderer.setClearColor(0x000000, 1);
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
TWEEN.update();
camera.lookAt( scene.position );
// rotate the cube - dropped value manipulation
cubeMesh.rotation.set(xRotation, yRotation, zRotation);
renderer.render( scene, camera );
}
// this is NOT WORKING
function changetexture() {
currentMat++;
if (currentMat >= MatCollection.length) {
currentMat = 0;
}
cubeMesh.material = MatCollection[currentMat];
cubeMesh.material.needsUpdate = true;
}
</script>
</body>
In my project, I am doing a lot more TWEENING (moving and rotating a lot of objects) and I am calling changetexture() from there...
When leaving out the line...
cubeMesh.material = MatCollection[currentMat];
from that function, everything works fine. The cube moves out and comes back into view showing always the same texture.
What should I change?
Thank you in advance for sharing your expertise.
Oliver
Done.
Instead of trying to preload the Material into an array of materials, I created an array of individual textures called MyTextures and applied a newly created material (using the textures from the MyTextures array) to each side of the cube mesh.
...
var MyTextures = [];
... then, in the init() function:
neheTextureSMALL = new THREE.ImageUtils.loadTexture("test3.jpg");
MyTextures.push( neheTextureSMALL );
for (var myy = 0; myy<imgNameArray.length;myy++) {
neheTexture = new THREE.ImageUtils.loadTexture(imgNameArray[myy]);
MyTextures.push( neheTexture );
}
... then in the changetexture() function:
cubeMesh.material.materials[0] = new THREE.MeshBasicMaterial({map: MyTextures[currentMat+1], side: THREE.DoubleSide });
cubeMesh.material.materials[1] = new THREE.MeshBasicMaterial({map: MyTextures[0], side: THREE.DoubleSide });
cubeMesh.material.materials[2] = new THREE.MeshBasicMaterial({map: MyTextures[0], side: THREE.DoubleSide });
cubeMesh.material.materials[3] = new THREE.MeshBasicMaterial({map: MyTextures[0], side: THREE.DoubleSide });
cubeMesh.material.materials[4] = new THREE.MeshBasicMaterial({map: MyTextures[currentMat+1], side: THREE.DoubleSide });
cubeMesh.material.materials[5] = new THREE.MeshBasicMaterial({map: MyTextures[currentMat+1], side: THREE.DoubleSide });
That works pretty well.
But it does not look good (the image seems to be split into many triangles which is another problem...). :-(