FlatShading on colored custom geometry - three.js

As soon as I push my own vertices to a geometry, the geometry is a solid color, instead of having colored shadows.
Applying this code to a THREE.PlaneGeometry called mesh gives the following shading:
var light = new THREE.DirectionalLight(0xffffff, 1);
light.castShadow = true;
light.shadowDarkness = 0.5;
// ..
THREE.MeshLambertMaterial({ color: 0x66e6b0, shading: THREE.FlatShading });
// ...
mesh.receiveShadow = true;
mesh.castShadow = true;
However, when I apply the same code to a THREE.Geometry() with custom vertices and faces, the geometry is solid black. How can I give the custom geometry the same shading as the plane geometry?
I can use THREE.MeshBasicMaterial but then there are no longer shadows on the faces.
Using vertexColors: THREE.FaceColors and coloring each face still gives all black.
A THREE.AmbientLight gives color but then there are no shadows on the faces.
Here is a fiddle of randomly generated faces that are all the same color. Instead, I would like them to have different shadows because they are different angles (as in the above image).

It is not the shadows that would produce an effect like that but a z-coordinate. In your jsfiddle all your triangles are on the xy-plane so they all have the same normal. So their lighting would be the same. So if you make the call like this:
geometry.vertices.push(new THREE.Vector3(Math.random() * 100, Math.random() * 100, Math.random() * 100));
and also light.castShadow = false; because it does not contribute to anything then you will get the variation that you want.

This problem of a geometry appearing all black will occur when any initial coordinate of a vertex appended to the geometry has an undefined value.
Even if the geometry is displayed, animates, and no errors are thrown, if an initial coordinate of a THREE.Vector3 is undefined, THREE.MeshLambertMaterial shading will not work.
This problem is demonstrated in the fiddle, where the use of undefined_variable prevents colored shading, and just yields a solid color.
To handle this, initialize all vertices to arbitrary values i.e. new THREE.Vector3(0, 0, 0) and then use the values of variables in animate().

Related

set transparent (opacity: 0) to some faces of a sphere geometry

I want to make half the faces of a sphere transparent and the other half colored.
How can I do that?
I've tried to set a transparent color, but it seems it doesn't work that way.
geometry = new THREE.SphereGeometry(1.0, 17, 17);
for (var i = 0; i < geometry.faces.length; i++) {
let x = Math.random();
//Here I'm trying to set a transparent color to half the faces of the sphere.
let color = 0
if (x < 0.5) {
color = '0x000000';
} else {
color = '0xffffff';
}
geometry.faces[i].color.setHex(color);
}
var material = new THREE.MeshPhongMaterial({ vertexColors: THREE.VertexColors });
sphere = new THREE.Mesh(geometry, material);
All the faces of the sphere are colored if I do in the way above.
I want half the faces to be randomly selected and to be transparent so that it will make the light inside the sphere scatter its rays like god rays effect, which is something like the one in the video below.
https://www.youtube.com/watch?v=suqFV7VGsL4
Looking at the GLSL shaders in three.js, three.js does not support alpha on vertex colors. It only uses Red, Green, and Blue, not the alpha.
To use vertex colors to make something transparent you'd need to write a custom shader or modify three.js's shaders

Can objects be hidden behind other transparent objects?

I have created a transparent floor from a PlaneGeometry. But the requirement is that other objects will rise up from beneath that plane. They must not be visible until they are above the floor.
Is it possible to hide those objects despite being behind something with transparency?
You could use a local clipping plane, so these objects will only be visible above the plane.
See this three.js example: https://threejs.org/examples/?q=clipping#webgl_clipping
Important parts:
// plane on ground/floor level
var clippingPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
// material of objects that will rise up
var material = new THREE.MeshPhongMaterial({
color: 0x80ee10,
clippingPlanes: [ clippingPlane ]
clipShadows: true
});

Three.js terrain shadowing

I've done a terrain using planegeometry object. I set a vertexes' y coordinate to bump my terrain. Then I added a directional light to my scene and see that there is no shadowing of the "hills" etc.
I added also a sphere and noticed that there is also no shadow on this terrain.
var light = new THREE.DirectionalLight(0xffffff, 1);
light.castShadow = true;
light.shadowCameraVisible = true;
light.position.set(-300, 120, -200); // CHANGED
scene.add(light);
scene.add( new THREE.DirectionalLightHelper(light, 0.2) );
Directional light with sphere above the terrain
But when I replaced directional light by a spotlight I've seen shadowing on a terrain that I want to have.
var slight = new THREE.SpotLight(0xffffff,1);
slight.position.set(-100,60,100);
slight.shadowCameraVisible = true;
scene.add(slight);
scene.add(new THREE.SpotLightHelper(slight, 0.5));
Spotlight with terrain
So the questions are:
how can I do a light that looks like sunshine so the terrain will be not plane color but depend on light? (in future it will be a part of a real city)
what should I do to see the objects' shadows on the terrain? (from fiddle example: sphere's shadow)
Thanks
You are modifying the vertices of your terrain. When you do so, you have to also modify the vertex normals. One way to do that is like so:
geometry.computeVertexNormals();
To create shadows you must enable them.
renderer.shadowMap.enabled = true;
three.js r.130

Unexpected mesh results from ThreeCSG boolean operation

I am creating a scene & have used a boolean function to cut out holes in my wall. However the lighting reveals that the resultant shapes have messed up faces. I want the surface to look like one solid piece, rather than fragmented and displaying lighting backwards. Does anyone know what could be going wrong with my geometry?
The code that booleans objects is as follows:
//boolean subtract two shapes, convert meshes to bsps, subtract, then convert back to mesh
var booleanSubtract = function (Mesh1, Mesh2, material) {
//Mesh1 conversion
var mesh1BSP = new ThreeBSP( Mesh1 );
//Mesh2 conversion
var mesh2BSP = new ThreeBSP( Mesh2 );
var subtract_bsp = mesh1BSP.subtract( mesh2BSP );
var result = subtract_bsp.toMesh( material );
result.geometry.computeVertexNormals();
return result;
};
I have two lights in the scene:
var light = new THREE.DirectionalLight( 0xffffff, 0.75 );
light.position.set( 0, 0, 1 );
scene.add( light );
//create a point light
var pointLight = new THREE.PointLight(0xFFFFFF);
// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
// add to the scene
scene.add(pointLight);
EDIT: Using WestLangley's suggestion, I was able to partially fix the wall rendering. And by using material.wireframe=true; I can see that after the boolean operation my wall faces are not merged. Is there a way to merge them?
Your problems are due to two issues.
First, you should be using FlatShading.
Second, as explained in this stackoverflow post, MeshLambert material only calculates the lighting at each vertex, and interpolates the color across each face. MeshPhongMaterial calculates the color at each texel.
You need to use MeshPhongMaterial to avoid the lighting artifacts you are seeing.
three.js r.68

zbuffer problems using 2D planes in THREE.JS

I am composing 2D planes with textures. I have 3 levels.
A background plane at z=0,
black shapes for conections at z=0.1 and
small planes with textures at z=0.2
the problem is that when I move the camera planes seems to change z position.
Planes are drawn in incorrect Z, it depend on the position of the camera. Moving the camera it changes again and looks very ugly.
Maybe I need to activate some ZBuffer property for correct drawing
WebGL init is like this and planes are exactly the same (only Z coord change)
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer._microCache = new MicroCache(); //cache de imagenes
renderer.setClearColor(0xeeeeee, 1);
document.body.appendChild(renderer.domElement);
// add directional light source
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1300).normalize();
scene.add(directionalLight);
//background plane
plane = new THREE.Mesh(new THREE.PlaneGeometry(200000, 200000, 1, 1), new THREE.MeshLambertMaterial({ color: 0xffffff, opacity: planeOpacity, transparent: true }););
plane.position.z = 0;
scene.add(plane);
Other planes are exactly the same but greater Z position
Help please!
Thanks!
Palomo
The thing you're seing is probably z-fighting. Internally, depth is represented by integer in GPU so there is only fixed number of distinct z-s between camera's near and far planes. The solution is to either move your planes apart or narrow camera's near-far range down.

Resources