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: .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.
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/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.
Share Improve this question edited Jun 29, 2015 at 19:57 Peter O. 32.9k14 gold badges84 silver badges97 bronze badges asked Feb 7, 2013 at 21:46 CabbiboCabbibo 1,4113 gold badges18 silver badges32 bronze badges3 Answers
Reset to default 14Sounds 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 bee 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 e 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!
Since your ranges are this big then you must be setting your camera near plane close to 0 and your far plane close to 1000000. But there is not enough z-resolution. You can read more about it at http://www.sjbaker/steve/omniv/love_your_z_buffer.html.
A solution, which I don't know how to implement, but could possibly work, is using two scenes, and two cameras.
One scene is for close stuff, and the other is for distant stuff. Each of the scenes is rendered using a camera which has a zNear and zFar appropriate to what is required. i.e. close scene has a camera with zNear = 0.1 and zFar = 10,000 and far scene has a camera with zNear = 10,000 and zFar = 6,000,000
The difficulty es with hooking up TrackballControls to both cameras in order to synchronize the scenes.