Sometimes to optimize early exits as for light volumes for example:
float distSquared( vec3 A, vec3 B )
{
vec3 C = A - B;
return dot( C, C );
}
// Early escape when the distance between the fragment and the light
// is smaller than the light volume/sphere threshold.
//float dist = length(lights[i].Position - FragPos);
//if(dist < lights[i].Radius)
// Let's optimize by skipping the expensive square root calculation
// for when it's necessary.
float dist = distSquared( lights[i].Position, FragPos );
if( dist < lights[i].Radius * lights[i].Radius )
{
// Do expensive calculations.
If you need the distance
later on simply:
dist = sqrt( dist )
EDIT: Another example.
Another use case that I've recently learnt, suppose that you want to have two positions: vec3 posOne
and vec3 posTwo
and you want the distance to each of those. The naive way would be to compute them independently: float distanceOne = distance( posOne, otherPos )
and float distanceTwo = distance( posTwo, otherPos )
. But you want to exploit SIMD! So you do: posOne -= otherPos; posTwo -= otherPos
so you are ready to compute the euclidean distance by SIMD: vec2 SIMDDistance = vec2( dot( posOne ), dot( posTwo ) );
and you can then use SIMD for the square root: SIMDDistance = sqrt( SIMDDistance );
where the distance to posOne is on the .x component of the SIMDDistance variable and the .y component contains the distance to posTwo.