Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do people use sqrt(dot(distanceVector, distanceVector)) over OpenGL's distance function?

When using ShaderToy I often see people using something like:

vec2 uv = fragCoord / iResolution;
vec2 centerPoint = vec2(0.5);

vec2 distanceVector = uv - centerPoint;
float dist = sqrt(dot(distanceVector, distanceVector));

over OpenGL's distance function:

vec2 uv = fragCoord / iResolution;
vec2 centerPoint = vec2(0.5);

float dist = distance(uv, centerPoint);

I'm just curious why this is (my guess is that it has something to do with speed or support for distance).

I loosely understand that if the arguments are the same, the square root of a dot product equals the length of the vector: the distance?

like image 414
bradleygriffith Avatar asked Jun 30 '16 01:06

bradleygriffith


3 Answers

Doing essentially the same thing, people often choose the sqrt option for one of two reasons: 1. They don't know about/remember the distance function 2. They are trusting themselves and their own math to prove that is not a problem to cause a bug (avoiding OpenGL problems)

like image 127
Jacolack Avatar answered Nov 07 '22 19:11

Jacolack


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.

like image 34
Felipe Gutierrez Avatar answered Nov 07 '22 19:11

Felipe Gutierrez


Using dot gives you a quick way to experiment with quadratic/linear function of distance.

like image 1
wiz Avatar answered Nov 07 '22 19:11

wiz