Bug 1759526 Comment 2 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to work with a quad to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );


    float s = sign(max(
        max(cross2(v0, e0), cross2(v1, e1)),
        max(cross2(v2, e2), cross2(v3, e3))
    ));

    // We can probably come up with a cheap sqrt approximation since we are only interested in d in [-0.5, 0.5].
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to work with a quad to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    // The in-out test relies on consistent winding order of the vertices.
    // Probably wrong with transforms that, say, invert an axis.
    float s = sign(max(
        max(cross2(v0, e0), cross2(v1, e1)),
        max(cross2(v2, e2), cross2(v3, e3))
    ));

    // We can probably come up with a cheap sqrt approximation since we are only interested in d in [-0.5, 0.5].
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to work with a quad to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    // This in/out test relies on consistent winding order of the vertices.
    // Probably wrong with transforms like scale(-1, 1).
    float s = sign(max(
        max(cross2(v0, e0), cross2(v1, e1)),
        max(cross2(v2, e2), cross2(v3, e3))
    ));

    // This one handles both windings:
    //float s = sign(
    //    max(
    //        max(cross2(v0, e0), cross2(v1, e1)),
    //        max(cross2(v2, e2), cross2(v3, e3))
    //    ) * max(
    //        max(-cross2(v0, e0), -cross2(v1, e1)),
    //        max(-cross2(v2, e2), -cross2(v3, e3))
    //    )
    //);


    // We can probably come up with a cheap sqrt approximation since we are only interested in d in [-0.5, 0.5].
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to work with a quad to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    float c0 = cross2(v0, e0);
    float c1 = cross2(v1, e1);
    float c2 = cross2(v2, e2);
    float c3 = cross2(v3, e3);
    // We could simplify the in/out test below with this if we could ensure
    // consistent vertex winding, but we probably can't with transforms
    // like scale(-1, 1).
    //float s = sign(max(max(c0, c1), max(c2, c3)));
    float s = sign(
        max(max(c0, c1), max(c2, c3)) * max(max(-c0, -c1), max(-c2, -c3))
    );

    // We can probably come up with a cheap sqrt approximation since we are only interested in d in [-0.5, 0.5].
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to work with a quad to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    float c0 = cross2(v0, e0);
    float c1 = cross2(v1, e1);
    float c2 = cross2(v2, e2);
    float c3 = cross2(v3, e3);
    // We could simplify the in/out test below with this if we could ensure
    // consistent vertex winding, but we probably can't with transforms
    // like scale(-1, 1).
    //float s = sign(max(max(c0, c1), max(c2, c3)));
    float s = sign(
        max(max(c0, c1), max(c2, c3)) * max(max(-c0, -c1), max(-c2, -c3))
    );

    // We can probably use a cheap sqrt approximation since we are only interested in d in [-0.5, 0.5].
    // The following one looks fine.
    // return d * 2.0 * s
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    float c0 = cross2(v0, e0);
    float c1 = cross2(v1, e1);
    float c2 = cross2(v2, e2);
    float c3 = cross2(v3, e3);
    // We could simplify the in/out test below with this if we could ensure
    // consistent vertex winding, but we probably can't with transforms
    // like scale(-1, 1).
    //float s = sign(max(max(c0, c1), max(c2, c3)));
    float s = sign(
        max(max(c0, c1), max(c2, c3)) * max(max(-c0, -c1), max(-c2, -c3))
    );

    // We can probably use a cheap sqrt approximation since we are only interested in
    // the distance in the range [-0.5, 0. The following one is probably good enough:
    // return d * 2.0 * s
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.
I played around with shadertoy, adapting https://www.shadertoy.com/view/XsXSz4# to get the signed distance of an arbitrary quad in screen space.

```C
float cross2(vec2 a, vec2 b) {
    return a.x * b.y - a.y * b.x;
}

float quad_distance(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec2 p3)
{
    // Vectors along each edge.
    vec2 e0 = p1 - p0;
    vec2 e1 = p2 - p1;
    vec2 e2 = p3 - p2;
    vec2 e3 = p0 - p3;

    // Vectors from the point to each vertex.
    vec2 v0 = p - p0;
    vec2 v1 = p - p1;
    vec2 v2 = p - p2;
    vec2 v3 = p - p3;

    vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0);
    vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0);
    vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0);
    vec2 pq3 = v3 - e3 * clamp(dot(v3, e3) / dot(e3, e3), 0.0, 1.0);

    float d = min(
        min(dot(pq0, pq0), dot(pq1, pq1)),
        min(dot(pq2, pq2), dot(pq3, pq3))
    );

    float c0 = cross2(v0, e0);
    float c1 = cross2(v1, e1);
    float c2 = cross2(v2, e2);
    float c3 = cross2(v3, e3);
    // We could simplify the in/out test below with this if we could ensure
    // consistent vertex winding, but we probably can't with transforms
    // like scale(-1, 1).
    //float s = sign(max(max(c0, c1), max(c2, c3)));
    float s = sign(
        max(max(c0, c1), max(c2, c3)) * max(max(-c0, -c1), max(-c2, -c3))
    );

    // We can probably use a cheap sqrt approximation since we are only interested in
    // the distance in the range [-0.5, 0.5]. The following one is probably good enough:
    // return d * 2.0 * s
    return sqrt(d) * s;
}
```

That would require passing 8 float varyings instead of 4 (not too bad), but also requires a lot more alu than the current implementation.

Back to Bug 1759526 Comment 2