I have a series of PlaneGeometry that I merge into a larger geometry. They can receive shadow from other objects, such as BoxGeometry, but the PlaneGeometry is not casting shadows, either stitched into the larger merged geometry or added to the scene separately. Is this intended behavior? Thank you!
Code:
EO.map.HandleChunk = function(chunkObj) {
var chunk = chunkObj.data;
var structures = chunkObj.structures;
//the main chunk geo
var chunkGeometry = new THREE.Geometry();
//material lists
var materialListDictionary = [];
var materialListIndex = [];
//individual geo reference
var geometry = new THREE.PlaneGeometry( 64, 64 );
//blank tile material
var material = new THREE.MeshPhongMaterial( { color: 0x001111, vertexColors: true, shading: THREE.SmoothShading } );
//individual tile mesh
var mesh = new THREE.Mesh( geometry, material );
//loop through tiles
for (var i = 0; i < chunk.length; i++) {
if (typeof EO.tiles.library[chunk[i].tile_id] === 'undefined') {
// tile does not exist in database, use blank tile material
mesh.material = material;
} else {
// tile exists in database, clone the source from tile library
mesh.material = EO.tiles.library[chunk[i].tile_id].clone(true);
}
//add material to dictionary if does not exist
var mat_array_index = materialListIndex.indexOf(chunk[i].tile_id);
if (mat_array_index < 0) {
materialListIndex.push(chunk[i].tile_id);
materialListDictionary.push(mesh.material);
mat_array_index = materialListIndex.length - 1;
}
//set tile position
mesh.position.set( chunk[i].x * 64, chunk[i].y * 64, 0 );
mesh.updateMatrix();
//merge to main chunk geometry
mesh.castShadow = true;
mesh.receiveShadow = true;
chunkGeometry.merge(mesh.geometry, mesh.matrix, mat_array_index);
}
//new structure loop, create them all as planes...
// [ Ceiling, North, East, South, West]
//// [ x, y, rotx, roty, rotz ];
var pi2 = Math.PI / 2;
var structureOffsetArray = [
[0, 0, 0, 0, 0],
[0, 32, pi2, 0, 0],
[32, 0, pi2, pi2, 0],
[0, -32, pi2, 0, 0],
[-32, 0, pi2, pi2, 0]
];
for (var s = 0; s < structures.length; s++) {
//grab a structure,
var structure = structures[s];
var x = structure.x;
var y = structure.y;
var height = structure.height;
var base = 32;
var texture_id = structure.texture_id;
//setup materials
var material = EO.structures.library[texture_id].clone();
var material2 = EO.structures.library[texture_id].clone();
var wallTexture = material2.map.clone();
mesh.material = material;
wallTexture.needsUpdate = true;
wallTexture.repeat.set(1, height);
material2.map = wallTexture;
for (var si = 0; si < 5; si++) {
//mesh.geometry = ;
//var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 64, base * height ), material );
//handle material key index
var materialKey = texture_id;
if (si > 0) {
mesh.geometry = new THREE.PlaneGeometry( 64, base * height );
materialKey = texture_id+'_'+height;
mesh.material = material2;
} else {
//base = 32;
mesh.geometry = new THREE.PlaneGeometry( 64, 64 );
}
var mat_array_index = materialListIndex.indexOf(materialKey);
if (mat_array_index < 0) {
materialListIndex.push(materialKey);
materialListDictionary.push(mesh.material);
mat_array_index = materialListIndex.length - 1;
}
var offset = structureOffsetArray[si];
if (si === 0) {
mesh.position.set( x * 64 + offset[0], y * 64 + offset[1], (base * height) );
} else {
mesh.position.set( x * 64 + offset[0], y * 64 + offset[1], (base * height) / 2 );
}
mesh.rotation.set( offset[2], offset[3], offset[4] );
mesh.geometry.computeFaceNormals();
mesh.updateMatrix();
mesh.castShadow = true;
mesh.receiveShadow = true;
chunkGeometry.merge(mesh.geometry, mesh.matrix, mat_array_index);
}
}
chunkGeometry.sortFacesByMaterialIndex();
var chunkMesh = new THREE.Mesh(chunkGeometry, new THREE.MeshFaceMaterial( materialListDictionary ) );
chunkMesh.castShadow = true;
chunkMesh.receiveShadow = true;
chunkMesh.name = "Chunk"
EO.three.scene.add(chunkMesh);
}
[ ] ...
[ ] All of them
[ ] Internet Explorer
[ ] All of them
Shadows currently need objects to be solid and, ideally, without back side surfaces and front side surfaces in the same position. Try using a BoxGeometry
with 0.01
height for now.
@mrdoob
line 105&106 at /src/renderers/webgl/WebGLShadowMap.js
this.renderReverseSided = true;
this.renderSingleSided = true;
set this.renderReverseSided = false;
can solve the problem.
Is there any special reason for this line?
thankyou very much gaomeng1900, u solve my one year struggle for PlaneMesh shadow.
this.renderReverseSided = false;//true;
this.renderSingleSided = false;//true;
I set both to false and now I have shadow on each side of PlaneMesh.
@nagakontot
actually there is a api for that
https://threejs.org/docs/index.html#api/renderers/WebGLRenderer.shadowMap
renderReverseSided = true
solves problems caused by precision. Please make sure everything works fine when u change it to false.
@gaomeng1900 that only works for PlaneGeometry
though...? Maybe we can make an exception in the code...
@mrdoob renderReverseSided = true
only works fine for closed geometries, not for unclosed geometry such as a semisphere/plane/anything with a hole on its face.
I've been hassling with this unintuitive bug, thinking I was doing something wrong.
The red squares should be casting shadows:
https://codepen.io/trusktr/pen/POrOoK?editors=0010
What's the solution that doesn't involve multiplying the polygon count by 6 (i.e. not converting from Plane to Box)?
I tried using a thin box in the following example (line 145), but it generates weird glitchy shadows that aren't supposed to be there:
https://codepen.io/trusktr/pen/EbBoLb
The only shadows should be from the sphere and the button, cast onto the background element.
If I make the thickness bigger (line 145), then the glitch goes away:
@gaomeng1900 that only works for PlaneGeometry though...? Maybe we can make an exception in the code...
What's the status of this idea? Seems like you guys know how to officially fix this. Decreasing my polygon count back down would be awesome!
Ah, maybe LightShadow.bias
can help reduce the artefacts I'm seeing. This is good enough
for now, but I would really really like to get Plane shadow working because it is imperative to what I'm making, and I don't want it to look as clean as possible.
@trusktr Please refrain from posting your help questions here.
https://stackoverflow.com/questions/44989568/three-js-plane-doesnt-cast-shadow
light.shadow.bias = - 0.01;
renderer.shadowMap.renderReverseSided = false;
Hello @WestLangley, I think it's nice to have these things listed here. Maybe it'll help someone.
Both "workarounds" listed in that SO question introduce other problems. I don't want to change rendering for all objects just to fix plane shadows, and thin boxes introduce unwanted artefacts on the "plane" edges in certain cases and cost more CPU power than necessary.
IMHO, this issue should be open still, and a solution should be at least desired.
Probably that solution is to make a special case for Planes and not to cull them. Eventually I'll try to see if I can do it unless someone gets to it first.
I gave @gaomeng1900's idea a shot: https://github.com/mrdoob/three.js/pull/12830
It'd be great to have this solved, so that Three can do its job in making rendering 3D simply easy for people in every way that it can.
Most helpful comment
@mrdoob
line 105&106 at /src/renderers/webgl/WebGLShadowMap.js
set
this.renderReverseSided = false;
can solve the problem.Is there any special reason for this line?