How to improve precision in a large scene with multi-cameras
Posted: Mon Dec 21, 2009 3:56 pm
I am faced with the following issue:
I have a large terrain; it extends for 1000 kilometers by 1000 kilometers.
I have two cameras showing 2 entities on different sides of the terrain.
One entity position is {0,0,0} and the other entity position is {1000000, 0, 1000000}. (1 = meter).
My terrain has houses, trees and such.
My problem is that I get depth fights in the camera showing the object that is far from the scene center.
The problem is a float precision issue.
If I will compile OGRE with Ogre::Real as a double instead of a float – I will still have issue – because the rendering API uses floats for its matrix (Ex: D3DMATRIX in d3d9 is defined as float m[4][4]).
Mattan and I talked this issue over and he had a good idea that I want to share with you and get responses to.
The idea:
1. Change Ogre::Real to be double.(Set OGRE_DOUBLE_PRECISION to true).
2. Each time the view matrix is set – transform it to {0,0,0} and save the transpose Vec3d. Each time a world matrix is set – subtract the saved view matrix transpose from the matrix.
The result is that the rendering will always be as the camera is in {0,0,0} – maximum float precision when rendering.
The only price I see is the performance – so let's analyze it:
The view matrix gets updated once per camera render – so no hit here.
The hit for the world matrix transpose is only 3 more "add" operations – for each world matrix update – so this is not a bottle neck.
The biggest hit is working with double as Ogre::Real – if you are using a 32 bit system. But – if you are running such a big scene – you must use a double for your location, right?
If the idea is valid and will work in my tests and such (and doesn't exist is some other way) - I want to add this option as a new compile switch.
What do you think?
I have a large terrain; it extends for 1000 kilometers by 1000 kilometers.
I have two cameras showing 2 entities on different sides of the terrain.
One entity position is {0,0,0} and the other entity position is {1000000, 0, 1000000}. (1 = meter).
My terrain has houses, trees and such.
My problem is that I get depth fights in the camera showing the object that is far from the scene center.
The problem is a float precision issue.
If I will compile OGRE with Ogre::Real as a double instead of a float – I will still have issue – because the rendering API uses floats for its matrix (Ex: D3DMATRIX in d3d9 is defined as float m[4][4]).
Mattan and I talked this issue over and he had a good idea that I want to share with you and get responses to.
The idea:
1. Change Ogre::Real to be double.(Set OGRE_DOUBLE_PRECISION to true).
2. Each time the view matrix is set – transform it to {0,0,0} and save the transpose Vec3d. Each time a world matrix is set – subtract the saved view matrix transpose from the matrix.
The result is that the rendering will always be as the camera is in {0,0,0} – maximum float precision when rendering.
The only price I see is the performance – so let's analyze it:
The view matrix gets updated once per camera render – so no hit here.
The hit for the world matrix transpose is only 3 more "add" operations – for each world matrix update – so this is not a bottle neck.
The biggest hit is working with double as Ogre::Real – if you are using a 32 bit system. But – if you are running such a big scene – you must use a double for your location, right?
If the idea is valid and will work in my tests and such (and doesn't exist is some other way) - I want to add this option as a new compile switch.
What do you think?