Advertisement

Relative-To-Eye math not working?

Started by April 07, 2020 06:08 PM
2 comments, last by Green_Baron 4 years, 9 months ago

Hi Everyone,

So, I'm writing a planet-scale renderer, in which I'm implementing Relative-To-Eye method to deal with precision problems; however, the final result doesn't quite match with the traditional rendering path, and I can't figure out why.

I'll put this simple, assuming left-handed system and:

camera = | 0, 0,-2 |

point  = | 1, 0, 0 |

worldView =  | 1  0  0  0 |
             | 0  1  0  0 |
             | 0  0  1  0 |
             | 1  0  2  1 |

proj =  | 1.54 0    0    0 |
        | 0    2.41 0    0 |
        | 0    0    1.47 1 |
        | 0    0   -1.41 0 |

Traditional method:

worldViewProj = | 1.5  0    0     0 |
                | 0    2.41 0     0 |
                | 0    0    1.47  1 |
                | 1.52 0    1.54  2 |
                
result = float4(point,1) * worldViewProj = | 3  0  1.54  2 |

result_h  = | 1.52  0  0.77  1 |   // after homogenous divide                 

Relative To Eye method:

(some computations here happen using double precision)

worldViewRTE = | 1  0  0  0 |  // from the original 'worldView' set 4th's row XYZ to 0's
               | 0  1  0  0 |
               | 0  0  1  0 |
               | 0  0  0  1 |
               
worldViweProjRTE = | 1.5  0    0    0 |  // worldViewRTE * proj
                   | 0    2.4  0    0 |
                   | 0    0    1.4  1 |
                   | 0    0   -1.41 0 |
                   
// set point position relative to eye
pointRTE = point - camera =  | 1  0  2 |

result = float4(pointRTE,1) * worldViewProjRTE = | 1.54  0  1.54  2 |

result_h = | 0.77  0  0.77  1 |  // after homogenous divide

As you can see in the examples above, the RTE method ends up with an X coordinate being half the value of that of the traditional method, when their values should end up being the same (or very close if you take the precision difference into account)…

The method works well if the point is at the origin.. both traditional and RTE values match, but if the point has any axis away from origin, the same half-value mismatch behavior shows up.

Any ideas what could be worong?

"lots of shoulddas, coulddas, woulddas in the air, thinking about things they shouldda couldda wouldda donne, however all those shoulddas coulddas woulddas ran away when they saw the little did to come"

Check a book called “3D Engine Design for Virtual Globes”. It have some information about RTE method.

Advertisement

The worlviewrte matrix is not the worldview matrix from above stripped from translation. The fourth row was also stripped, it seems. Edit: scrub, i do the position subtraction in the vertex shader and i'm using column major order, that's why it looks different from my code. It's been some time since i last touched this :-) The principle looks right, probably just a detail missing …

If you search “relative to eye” you'll find quite a few discussions on the topic and its implementation in here.

Maybe this working example helps for comparison, all standard. I do double→float conversion and camera/vertex-position subtraction in the vertex shader.

// view and model matrix in double precision
const omath::dmat4 view{ omath::lookAt(
	cam->getPosition(),
	cam->getPosition() + omath::dvec3{ cam->getFront() },
	omath::dvec3{ cam->getUp() } )
};
const omath::dmat4 mv{ view * m_modelMatrix };
// this matrix can be used for all objects in same coord system
// rte matrix in single precision, translation set to 0
const omath::mat4 mvRTE{
	omath::vec4{ mv[0] },
	omath::vec4{ mv[1] },
	omath::vec4{ mv[2] },
	omath::vec4{ 0.0f, 0.0f, 0.0f, static_cast<float>( mv[3][3] ) }
};
// Simply assign rte matrix to shader uniform
setModelViewProjectionMatrixRTE( cam->getPerspectiveMatrix() * mvRTE );

This topic is closed to new replies.

Advertisement