Color a tetrahedron in three.js - three.js

In three.js, I'm trying to draw a tetrahedron using THREE.TetrahedronGeometry where each face is a different color. When I use MeshNormalMaterial, each vertex has a different color but the faces are color gradients between the vertexes. This works for a BoxGeometry, but not for TetrahedronGeometry.
I tried using PhongMaterial with shading: THREE.FlatShading but that just gives me black or white faces.
I tried writing my own ShaderMaterial and in the fragment material, I color using the normal vector, but that also gets the gradient affect.
I'm sure I'm missing something obvious, but can't see it...

For versions of three.js prior to r125*, this is how you do it:
var geo = new THREE.TetrahedronGeometry(sphereRadius, 0);
for ( var i = 0; i < geo.faces.length; i ++ ) {
geo.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
var material = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
shading: THREE.FlatShading,
vertexColors: THREE.VertexColors
})
var mesh = new THREE.Mesh( geo, material );
So you need THREE.FlatShader, THREE.VertexColors, and then you need to assign the face colors.
For later versions, see how to render a tetrahedron with different texture on each face (using three.js)?.
* THREE.Geometry will be removed from core with r125

Related

Three.js: How to prevent parts of mesh from shape dissapearing at larger distance

I have a geometry that should be visible from a close and large distance. It is a shape geometry. The material used is the basic mesh material. The code is like this:
var shape = new THREE.Shape(geoPoints);
var geometry = new THREE.ShapeGeometry(shape);
var material = new THREE.MeshBasicMaterial({
color: 0x0000FF,
wireframe: true
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
When I use the wireframe property of the material, the geometry stays entirely visible. However, when I turn off the wireframe parts of the mesh dissapear from larger distance. This can be seen in the added figures:
Mesh basic material, wireframe off
Mesh basic material, wireframe on
How can this be solved? Many thanks in advance.

Displacement map on BoxGeometry only moves edges?

I'm just starting to get my bearings with threejs and I'm having an issue using Displacement Maps.
http://codepen.io/jpschwinghamer/pen/BWPebJ
I have a simple BoxGeometry that I'm trying to apply textures to a phong material. All seem to work correctly except for the displacement map. I made sure to add segments to the BoxGeometry instantiation. Is there some bit of magic that I'm missing to make my displacement map work correctly?
Consider this code:
var animate, camera, displacement, geometry, light, light1, map, material, mesh, normal, reflection, renderer, roughness, textureLoader;
renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('canvas'),
antialiased: true
});
renderer.setClearColor(0xfff000);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
window.scene = new THREE.Scene();
light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
light1 = new THREE.PointLight(0xffffff, 0.6);
scene.add(light1);
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
geometry = new THREE.BoxGeometry(100, 100, 100, 10, 10, 10);
material = new THREE.MeshPhongMaterial({
map: map,
normalMap: normal,
normalScale: new THREE.Vector2(30, -1),
roughnessMap: roughness,
reflectionMap: reflection,
displacementMap: displacement,
displacementScale: 1,
displacementBias: 0
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, -700);
scene.add(mesh);
animate = function() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
requestAnimationFrame(animate);
return renderer.render(scene, camera);
};
animate();
The problem with your displacement map is that there is very little variation in the shades of grey (see it here).
The lowest points should be black and the highest should be white (or the other way around, I forget).
You would also need to have enough verticies for this to affect.
I think though that this map should be assigned to the bump map.
But... you probably don't want to use a bump map and normal map. it's usually one or the other.
But, having a look at the normal map you are loading, it is having no effect because it is all the same color. (see it here), so therefore, it's only the bump map that you need.
Also, MeshPhongMaterial does not seem to have roughnessMap or reflectionMap uniforms/properties, so these are doing nothing.
So basically, you only need to load you map and your displacement map, but put the displacement map on the bump map instead.
Maybe also your roughness image putting it on your specularMap.
EDIT.
Embedding code here does not seem to run because of CORS on the images.
See a FIDDLE HERE
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
//normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
//reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
// Create material
material = new THREE.MeshPhongMaterial({
map: map,
//normalMap: normal,
//normalScale: new THREE.Vector2(30, -1),
//roughnessMap: roughness,
//reflectionMap: reflection,
bumpMap: displacement,
bumpScale: 100,
//displacementBias: 0
specularMap: roughness
});
I believe the problem is that the BoxGeometry only contains 4 vertices per side. When you apply a displacement map, you actually move the positions of the vertices where a normal map would "fake" this on a fragment level.
To solve your problem, I would try with a geometry with a higher number of vertices. A sphere works fine for testing. Then import/generate a box geometry with more vertices.
Hope this helps!

Drawing edges of a mesh in Three.js

Is there something as Stroke to draw the edges of a mesh?
I would like to have my object to look like this:
EDIT: This answer was outdated, and has been updated.
If you want to render only the edges of your mesh, you can use EdgesGeometry.
var geometry = new THREE.EdgesGeometry( mesh.geometry );
var material = new THREE.LineBasicMaterial( { color: 0xffffff } );
var wireframe = new THREE.LineSegments( geometry, material );
scene.add( wireframe );
You can also use THREE.WireframeGeometry.
For an example showing how to render both edges and faces, see this stackoverflow answer.
three.js r.94

Threejs Raycasting a Sprite-Canvas Object is inaccurate [duplicate]

I am trying to use THREE.Raycaster to show an html label when the user hover an object. It works fine if I use THREE.Mesh but with THREE.Sprite it looks like that there is a space that increases with the scale of the object.
The creation process is the same for both scenario, I only change the type based on USE_SPRITE variable.
if ( USE_SPRITE ) {
// using SpriteMaterial / Sprite
m = new THREE.SpriteMaterial( { color: 0xff0000 } );
o = new THREE.Sprite( m );
} else {
// using MeshBasicMaterial / Material
m = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
o = new THREE.Mesh(new THREE.PlaneGeometry( 1, 1, 1 ), m );
}
https://plnkr.co/edit/J0HHFMpDB5INYLSCTWHG?p=preview
I am not sure if it is a bug with THREE.Sprite or if I am doing something wrong.
Thanks in advance.
three.js r73
I would consider this a bug in three.js r.75.
Raycasting with meshes in three.js is exact. However, with sprites, it is an approximation.
Sprites always face the camera, can have different x-scale and y-scale applied (be non-square), and can be rotated (sprite.material.rotation = Math.random()).
In THREE.Sprite.prototype.raycast(), make this change:
var guessSizeSq = this.scale.x * this.scale.y / 4;
That should work much better for square sprites. The corners of the sprite will be missed, as the sprite is treated as a disk.
three.js r.75

three js envMap using one texture

I have a code:
var urls = [ 'img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png' ];
var textureCube = THREE.ImageUtils.loadTextureCube( urls, new THREE.CubeRefractionMapping );
var cubeMaterial3 = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube, refractionRatio: 0.98, reflectivity:0.9 } );
mesh = new THREE.Mesh( wormholeGeom, cubeMaterial3 );
scene.add(mesh);
This successfully works and inserts sphere with refraction map.
But i do not using skybox, but skysphere where is whole sky represented by one texture.
Is the way to make a refraction mapping from one texture?
Not by array of six textures?
I tried many thinks (THREE.ImageUtils.loadTexture,THREE.SphericalRefractionMapping too) but no luck.
Documentation is "TODO".
This is my goal, but with one texture in skydome. There are used 6 textures in square to make sky.

Resources