I am currently working on a project that involves workinging in scenes with objects ranging from 10 - 1000000 in size. I have been having an issue where when I am in the large range of these sizes, the objects start to 'shimmer' This happens only when objects intersect, and then it gets more and more 'violent' as the camera moves away from the object.
I've uploaded an image of the problem here: https://i.sstatic.net/wu1lz.jpg
Although I have no idea what is causing this, I have a few possible ideas of what could be causing it:
First off, Is that I am just working at sizes that are too big for three.js / webgl
Second possibility I was thinking could be an issue is the use of the camera controls that I have made which are below:
if(mouseIsDown == true){
if(this.movementSpeed < this.maxSpeed){
this.movementSpeed += this.acceleration
}else{
this.movementSpeed = this.maxSpeed
}
}else{
if(this.movementSpeed > this.minSpeed){
this.movementSpeed = this.movementSpeed/this.deceleration
}else{
this.movementSpeed = this.minSpeed
}
}
Where this.minSpeed = 0, and this.movementSpeed is used to move the camera like so:
var actualSpeed = delta * this.movementSpeed;
this.object.translateZ( -actualSpeed * forwardOrAuto );
this.object.translateX( actualSpeed * sideSpeed );
this.object.translateY( actualSpeed * upSpeed );
I didn't think that this would be the issue, but since the movement speed is never actually equal to zero, it could be an issue. Even when the movement speed is at 10^-20 or -30 the shimmering still happens.
I am also on r.55, if that matters.
Sounds like precision problems. Movement can amplify the effect of rounding errors. When working on a model of the solar system (uom: meters) in three.js, I ran into many issues with "flickering" textures/models myself. gaitat is absolutely correct that you are experiencing z-buffer depth precision issues. There are a few ways that my partner and I dealt with it.
The z-buffer is not linear. sjbaker's site mentioned by gaitat will make that quite clear as it did for me months ago. Most z-buffer precision is found in the near. If your objects are be up to 1000000 units in size, then the objects themselves, not to mention the space between them, are already outside of the range of effective precision. One solution used by many, many video games out there, is to not move the player(camera), but instead move the world. This way, as something gets closer to the camera, it's precision increases. This is most important for textures on large overlapping objects far away (flickering/occlusion), or for small meshes far from the axial origin, where rounding problems become severe enough to jump meshes out of view. It is definitely easier said than done though, as you either have to make a "just in time" calculation to move everything in respect to the player (and still suffer rounding errors) or come up with a more elegant solution.
You will lose very little near precision with very high far numbers, but you will gain considerable precision in the mid-range with slightly larger near numbers. Even if the meshes you are working with can be as small as 10 units, a near camera setting of 10 or 100 might buy you some slack. Camera settings are not the only way to deal with the z-buffer.
polygonOffset - You effectively tell the z-buffer which thing (material on a mesh) belongs on top. It can introduce as many problems as it solves though, and can take quite a bit of tuning. Consider it akin to z-index in css, but a bit more fickle. Increasing the offset on one material to make sure it is rendered over something in the far, may make it render over something in the near. It can snowball, forcing you to set offsets on most of your objects. Factor and unit numbers are usually between -1.0 and 1.0 for polygonOffset, and may have to be fiddled with.
depthWrite=false - This means "do not write to the depth-buffer" and is great for a material that should always be rendered "behind" everything. Good examples are skyboxes and backgrounds.
Our project used all the above mentioned methods and still had mediocre results, though we were dealing with numbers as large as 40 Astronomical Units in meters (Pluto).
"They" call it "z-fighting", so fight the good fight!