Reflective material in THREE.js - javascript

How can I create a material that reflects other shapes from the scene? I have tried the reflectivity property but it didn't reflect anything.
There is an example that seems to have this effect
It doesn't look like standard materials were used to create this.

To go into a bit of the theory: a reflection is basically an image of the scene taken from a certain position. So if you want a planar mesh to serve as a mirror, you'll have to add a camera at that position, have it render the scene to a texture in the animation loop, and then use that texture in the material for the planar mesh. I would also recommend looking at http://stemkoski.github.io/Three.js/Reflection.html in addition to the examples WestLangley mentioned.
Also, play around with settings; for a less reflective effect, for example, try:
var mirrorMaterial = new THREE.MeshBasicMaterial( { color: 0x111111, envMap: mirrorCamera.renderTarget } );
or
var mirrorMaterial = new THREE.MeshPhongMaterial( { emissive: 0x111111, envMap: mirrorCamera.renderTarget } );

https://threejs.org/examples/#webgl_materials_cubemap
I did it with the above example:
new THREE.MeshLambertMaterial ({
map: texture,
envMap: scene.background,
combine: THREE.MixOperation,
reflectivity: .5
})
The key variable, as i understand, is THREE.MixOperation

Related

Three.js use multiple materials on one mesh

I am trying to understand how to add multiple materials to a mesh. I want to take the existing material and apply another slightly transparent material to my existing mesh. Right now, passing it as an array it just disappears. I know I am missing something, just not sure what that is. The end goal is so I can animate the opacity of the new material in/out over the existing one.
Original Material
const originalMaterial = child.material.clone();
New Material
const newMaterial = new THREE.MeshStandardMaterial({
name: 'New Mat',
map: newTexture,
emissiveMap: newTextureMap,
side: THREE.DoubleSide,
opacity: .5,
transparent: true
});
Combining them
child.material = [originalMaterial, newMaterial]
child.material.needsUpdate = true
WebGL doesn't allow for multiple materials on a single mesh. That's why the THREE.Mesh constructor only allows one geometry, and one material.
To do what you want, you could create two meshes, with one material's transparency set to 0.5. But more frequently you would just use a single mesh, and assign variations in opacity through the .alphaMap texture. This would give you more flexibility because you can have many more transparency values on a single object, without having to create new materials for each:
var textureLoader = new THREE.TextureLoader();
var alphaTexture = textureLoader.load("path/to/alpha.png");
mesh.material.alphaMap = alphaTexture;
mesh.material.transparent = true; // <- don't forget this!

Three.js - how to create custom shapes

I´m using Three.js and trying to create some custom shapes, similar to one that appears in a project from one of agencies using threejs:
three.js featured project esample
How did they generated these boxes with holes inside? (on that examples
boxes basically have only borders around and are empty inside).
As I saw in the code (I was trying to figure out myself) they use BoxGeometry but I have no idea how to accomplish that. Does anyone know or can give me any directions? It would be really helpfull as i´m stuck with this and have no idea on how to create them.
So in THREE.js Meshes represent any kind of 3D object. They combine Geometries and Shaders. Generally to create a mesh you call
var mesh = new THREE.Mesh( geometry, shader );
If you use any of the builtin shaders (also known as Materials [ MeshBasicMaterial, MeshLambertMaterial, etc]) they have a wireFrame boolean attribute that allows this functionality.
var geometry = new THREE.BoxGeometry( x, y, z ),
material = new THREE.MeshBasicMaterial( {
wireFrame: true, // This makes the object appear wireframe
color: 0xffffff // You can alter other properties
});
var box = new THREE.Mesh( geometry, material );
// You can also change it later
box.material.wireFrame = false;

Calculating light for custom geometry in Three.js

I've created a custom geometry and I've used geometry.computeFaceNormals() to get the lighting right. So far so good.
The problem comes when I animate the geometry. In the animation loop I call again geometry.computeFaceNormals() but the faces' lighting doesn't change.
Here is a fiddle with the example:
You are updating the vertices of your geometry, so typically, your normals must also be updated for the shading to be correct.
However, since you want flat shading, there is another solution.
MeshPhongMaterial generates flat shading using the OES_standard_derivatives extension. This means that geometry normals do not have to be specified or updated when vertices change.
All you have to do is use the following pattern, and flat shading will "just work" -- provided the extension is supported.
var material = new THREE.MeshPhongMaterial( {
color: 0xFFFFFF,
shading: THREE.FlatShading
} );
three.js r.80

See back of mapped material with Three.js and Physijs

I have created a very basic cube using Three.js and Physijs. I am mapping a texture that has transparency, and I would like to see the texture on the other side of the cube through the transparency. Right now, I see the background through the transparency, but not the texture on the back of the cube.
var cube = new Physijs.BoxMesh(
new THREE.BoxGeometry( 2, 2, 2),
new THREE.MeshPhongMaterial( { map: THREE.ImageUtils.loadTexture('border.png') } ),
1 );
The texture used:
The result:
As you can see, the background shows through the cube, but not the texture on the back faces. I guess that the back of a 2d texture can't be seen, but it there anyway for me to apply the texture to both sides of each face then?
This is my first go with Threejs, and there looks to be a lot to take in, so I hope I haven't missed something obvious :)
Setting the side to THREE.DoubleSide may does it for you:
var material = new THREE.MeshPhongMaterial( {
map: new THREE.TextureLoader().load( "image.png" ),
transparent: true,
side: THREE.DoubleSide // apply to both sides of the faces
} );
But the illusion is not perfect as you can see here:

Three.js - Light doesn't work on texture

I'm trying to make a simple solar system with three.js, I have finished everything, now I want to add some shading, but apparently it doesn't work when working on textures.
loader.load("earth.jpg", function ( texture ) {
var geometry = new THREE.SphereGeometry( 100, 20, 20 ),
material = new THREE.MeshLambertMaterial({
map: texture,
overdraw: true,
}),
mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
});
If I replace map: texture with color: 0xffffff it works very well, but when I add a texture, the light shading disappears.
Why lights doesn't works on textures?
Maybe should I create two spheres for every planet? One with a texture and another transparent with shadow?
This is a limitation of CanvasRenderer. It does not support MeshLambertMaterial and diffuse textures in combination.
You will have to switch to WebGLRenderer.
three.js r.65

Categories

Resources