After I have covered a certain distance with the camera, I would like to carry out a position transformation in order to avoid coordinate values that are too large.
To do this, I created a function that moves the scene and the camera when a limit is reached. First of all, this works very well. I don’t notice anything about the transformation and it doesn’t seem to be a computationally intensive affair, since neither the CPU nor the GPU show any performance peaks. The shaders that require the camera position also work perfectly because the camera is not part of the scene. Obviously all vertices of all objects inherit the translation of the scene position so everything is correct. The only thing I notice at first is that the coordinate values of the camera jump to the origin in the display. I imagined it exactly like that.
But what I didn’t imagine is the jittering of the whole scene when I move further after a transformation. Rotations show no jitter. Since neither the GPU nor the CPU fails, it must be something else.
Does anyone have experience with this topic and can imagine what it might be? Did I perhaps forget to take something into account somewhere during the transformation?
TransformCameraToOrigin() {
const currentCameraPosition = this.camera.position.clone();
this.scene.position.sub(currentCameraPosition);
this.camera.position.set(0, 0, 0);
}
//In the render loop
const cameraDistance = this.camera.position.length();
if (cameraDistance >= 20000) { //after 20 km
this.TransformCameraToOrigin();
}
The mechanism is very simple. But since this is my first time doing this, I may be missing something important
The way you describe it it might be caused by too large values. GPUs are fast calculators, but not very precise. It doesn’t matter whether the final values are withing the precision of GPU’s floats, also important is that all intermediate values are also relatively small.
Here is a simple example with jittering:
https://codepen.io/boytchev/pen/abRJMgK
And here is what I guess is happening in your case:
- scene is 0, but at some point the camera becomes 20000
- the transformation of origin is activated immediately
- the scene becomes -20000, the camera becomes 0
- you are happy, because the camera position is again small
- the GPU is not happy, because it still receives a large value (20000 and -20000 are equally large)
I’ve now tried this with 2000 and the same phenomenon occurs. When I turn the camera there are no jitters. When I stand still also everything is clean. Jitters only come when I move forward. But 2000 isn’t a huge value now.
So far I have used floating point origin and chosen the camera as the origin. This works quite well, but the camera itself can still have very high values. That’s why I came up with the idea of moving the scene.
The link in my post has two objects at (0,0,0) and a camera at (0,10,10). Although all these numbers are small, the computations in the GPU get crazy, because there is a vertex coordinate 10000 in one of the geometries.
Edit: this may give some ideas → Fixing Camera Shake on Single Precision GPUs
I’ve now added a box in a distance of 10 km and it doesn’t jitter. The transformation does not seem to be the cause if primitives are presented cleanly.
The cause must therefore lie in my self-created buffer geometry with the self-created shaders. Then I’ll close the point again so that it doesn’t hang around here in the forum as an unresolved point. With my custom geometry I will have to look for myself where I missed something.
P.S. Here is an addition to where the problem was for me:
I passed the cameraPosition to the shader of my geometry. After the coordinate transformation, the camera is in the origin. My assumption was that the vertex attributes position are global. But they are not that, but rather they are seen relative to the scene. So if the scene e.g. 100000 away from the origin and a vertex seen from the scene is 100 away from the scene origin, then the shader only sees this locale 100. The height in my scene is 0. After the transformation the scene is at y = -1000 and the camera at y = 0. However, the shader sees all vertices at y = 0 and not at y = -1000. Therefore, the shader saw the height difference as 0 and therefore the calculations in the shader were incorrect, which led to jumps. So the shader needs a relative cameraPosition:
const tempCameraPosition = cameraPosition.clone();
const relativePosition = tempCameraPosition.sub(scenePosition);