tor-browser

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

ps_quad_conic_gradient.glsl (2908B)


      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 /// This shader renders radial gradients in a color or alpha target.
      6 
      7 #include ps_quad,gradient
      8 
      9 #define PI                  3.141592653589793
     10 
     11 // x: start offset, y: offset scale, z: angle
     12 // Packed in to a vector to work around bug 1630356.
     13 flat varying highp vec3 v_start_offset_offset_scale_angle_vec;
     14 #define v_start_offset v_start_offset_offset_scale_angle_vec.x
     15 #define v_offset_scale v_start_offset_offset_scale_angle_vec.y
     16 #define v_angle v_start_offset_offset_scale_angle_vec.z
     17 
     18 varying highp vec2 v_dir;
     19 
     20 #ifdef WR_VERTEX_SHADER
     21 struct ConicGradient {
     22     vec2 center;
     23     vec2 scale;
     24     float start_offset;
     25     float end_offset;
     26     float angle;
     27     // 1.0 if the gradient should be repeated, 0.0 otherwise.
     28     float repeat;
     29 };
     30 
     31 ConicGradient fetch_conic_gradient(int address) {
     32     vec4[2] data = fetch_from_gpu_buffer_2f(address);
     33 
     34     return ConicGradient(
     35         data[0].xy,
     36         data[0].zw,
     37         data[1].x,
     38         data[1].y,
     39         data[1].z,
     40         data[1].w
     41     );
     42 }
     43 
     44 void pattern_vertex(PrimitiveInfo info) {
     45     ConicGradient gradient = fetch_conic_gradient(info.pattern_input.x);
     46     v_gradient_address.x = info.pattern_input.y;
     47     v_gradient_repeat.x = gradient.repeat;
     48 
     49     // Store 1/d where d = end_offset - start_offset
     50     // If d = 0, we can't get its reciprocal. Instead, just use a zero scale.
     51     float d = gradient.end_offset - gradient.start_offset;
     52     v_offset_scale = d != 0.0 ? 1.0 / d : 0.0;
     53 
     54     v_angle = PI / 2.0 - gradient.angle;
     55     v_start_offset = gradient.start_offset * v_offset_scale;
     56     v_dir = ((info.local_pos - info.local_prim_rect.p0) * gradient.scale - gradient.center);
     57 }
     58 
     59 #endif
     60 
     61 
     62 #ifdef WR_FRAGMENT_SHADER
     63 
     64 // From https://math.stackexchange.com/questions/1098487/atan2-faster-approximation
     65 float approx_atan2(float y, float x) {
     66     vec2 a = abs(vec2(x, y));
     67     float slope = min(a.x, a.y) / max(a.x, a.y);
     68     float s2 = slope * slope;
     69     float r = ((-0.0464964749 * s2 + 0.15931422) * s2 - 0.327622764) * s2 * slope + slope;
     70 
     71     r = if_then_else(float(a.y > a.x), 1.57079637 - r, r);
     72     r = if_then_else(float(x < 0.0),   3.14159274 - r, r);
     73     // To match atan2's behavior, -0.0 should count as negative and flip the sign of r.
     74     // Does this matter in practice in the context of conic gradients?
     75     r = y < 0.0 ? -r : r;
     76 
     77     return r;
     78 }
     79 
     80 vec4 pattern_fragment(vec4 color) {
     81     // Use inverse trig to find the angle offset from the relative position.
     82     vec2 current_dir = v_dir;
     83     float current_angle = approx_atan2(current_dir.y, current_dir.x) + v_angle;
     84     float offset = fract(current_angle / (2.0 * PI)) * v_offset_scale - v_start_offset;
     85 
     86     color *= sample_gradient(offset);
     87     return color;
     88 }
     89 
     90 #endif