tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

transform.glsl (4996B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2  * License, v. 2.0. If a copy of the MPL was not distributed with this
      3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 flat varying highp vec4 vTransformBounds;
      6 
      7 #ifdef WR_VERTEX_SHADER
      8 
      9 #define VECS_PER_TRANSFORM   8U
     10 uniform HIGHP_SAMPLER_FLOAT sampler2D sTransformPalette;
     11 
     12 void rectangle_aa_vertex(vec4 local_bounds) {
     13     vTransformBounds = local_bounds;
     14 }
     15 
     16 struct Transform {
     17     mat4 m;
     18     mat4 inv_m;
     19     bool is_axis_aligned;
     20 };
     21 
     22 Transform fetch_transform(int id) {
     23     Transform transform;
     24 
     25     transform.is_axis_aligned = (id >> 23) == 0;
     26     int index = id & 0x007fffff;
     27 
     28     // Create a UV base coord for each 8 texels.
     29     // This is required because trying to use an offset
     30     // of more than 8 texels doesn't work on some versions
     31     // of macOS.
     32     ivec2 uv = get_fetch_uv(index, VECS_PER_TRANSFORM);
     33     ivec2 uv0 = ivec2(uv.x + 0, uv.y);
     34 
     35     transform.m[0] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(0, 0));
     36     transform.m[1] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(1, 0));
     37     transform.m[2] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(2, 0));
     38     transform.m[3] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(3, 0));
     39 
     40     transform.inv_m[0] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(4, 0));
     41     transform.inv_m[1] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(5, 0));
     42     transform.inv_m[2] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(6, 0));
     43     transform.inv_m[3] = TEXEL_FETCH(sTransformPalette, uv0, 0, ivec2(7, 0));
     44 
     45     return transform;
     46 }
     47 
     48 // Return the intersection of the plane (set up by "normal" and "point")
     49 // with the ray (set up by "ray_origin" and "ray_dir"),
     50 // writing the resulting scaler into "t".
     51 bool ray_plane(vec3 normal, vec3 pt, vec3 ray_origin, vec3 ray_dir, out float t)
     52 {
     53     float denom = dot(normal, ray_dir);
     54     if (abs(denom) > 1e-6) {
     55         vec3 d = pt - ray_origin;
     56         t = dot(d, normal) / denom;
     57         return t >= 0.0;
     58     }
     59 
     60     return false;
     61 }
     62 
     63 // Apply the inverse transform "inv_transform"
     64 // to the reference point "ref" in CSS space,
     65 // producing a local point on a Transform plane,
     66 // set by a base point "a" and a normal "n".
     67 vec4 untransform(vec2 ref, vec3 n, vec3 a, mat4 inv_transform) {
     68     vec3 p = vec3(ref, -10000.0);
     69     vec3 d = vec3(0, 0, 1.0);
     70 
     71     float t = 0.0;
     72     // get an intersection of the Transform plane with Z axis vector,
     73     // originated from the "ref" point
     74     ray_plane(n, a, p, d, t);
     75     float z = p.z + d.z * t; // Z of the visible point on the Transform
     76 
     77     vec4 r = inv_transform * vec4(ref, z, 1.0);
     78     return r;
     79 }
     80 
     81 // Given a CSS space position, transform it back into the Transform space.
     82 vec4 get_node_pos(vec2 pos, Transform transform) {
     83     // get a point on the scroll node plane
     84     vec4 ah = transform.m * vec4(0.0, 0.0, 0.0, 1.0);
     85     vec3 a = ah.xyz / ah.w;
     86 
     87     // get the normal to the scroll node plane
     88     vec3 n = transpose(mat3(transform.inv_m)) * vec3(0.0, 0.0, 1.0);
     89     return untransform(pos, n, a, transform.inv_m);
     90 }
     91 
     92 #endif //WR_VERTEX_SHADER
     93 
     94 #ifdef WR_FRAGMENT_SHADER
     95 
     96 // Assume transform bounds are set to a large scale to signal they are invalid.
     97 bool has_valid_transform_bounds() {
     98     return vTransformBounds.w < 1.0e15;
     99 }
    100 
    101 float rectangle_aa_fragment(vec2 local_pos) {
    102     // Ideally we want to track distances in screen space after transformation
    103     // as signed distance calculations lose context about the direction vector
    104     // to exit the geometry, merely remembering the minimum distance to the
    105     // exit. However, we can't always sanely track distances in screen space
    106     // due to perspective transforms, clipping, and other concerns, so we do
    107     // this in local space. However, this causes problems tracking distances
    108     // in local space when attempting to scale by a uniform AA range later in
    109     // the presence of a transform which actually has non-uniform scaling.
    110     //
    111     // To work around this, we independently track the distances on the local
    112     // space X and Y axes and then scale them by the independent AA ranges (as
    113     // computed from fwidth derivatives) for the X and Y axes. This can break
    114     // down at certain angles (45 degrees or close to it), but still gives a
    115     // better approximation of screen-space distances in the presence of non-
    116     // uniform scaling for other rotations.
    117     //
    118     // Get signed distance from local rect bounds.
    119     vec2 d = signed_distance_rect_xy(
    120         local_pos,
    121         vTransformBounds.xy,
    122         vTransformBounds.zw
    123     );
    124 
    125     // Find the appropriate distance to apply the AA smoothstep over.
    126     vec2 aa_range = compute_aa_range_xy(local_pos);
    127 
    128     // Only apply AA to fragments outside the signed distance field.
    129     return distance_aa_xy(aa_range, d);
    130 }
    131 
    132 float rectangle_aa_rough_fragment(vec2 local_pos) {
    133     return point_inside_rect(
    134         local_pos,
    135         vTransformBounds.xy,
    136         vTransformBounds.zw
    137     );
    138 }
    139 
    140 #endif //WR_FRAGMENT_SHADER