packages feed

gelatin-shaders-0.1.0.0: shaders/simple2d.frag

#version 330 core

in vec4 fcolor;
in vec2 fuv;
in vec3 fbez;
in vec2 fbezuv;

out vec4 fragColor;

uniform int primitive;
uniform bool hasUV;
uniform sampler2D sampler;
uniform sampler2D mainTex;
uniform sampler2D maskTex;
uniform float thickness;
uniform float feather;
uniform float sumlength;
uniform vec2 cap;
uniform float alpha;
uniform vec4 mult;

uniform vec4 replaceColor;
uniform bool shouldColorReplace;

// Primitive types
const int PrimTri  = 0;
const int PrimBez  = 1;
const int PrimLine = 2;
const int PrimMask = 4;

// Types for rendering line caps
const float CapNone   = 0;
const float CapButt   = 1;
const float CapSquare = 2;
const float CapRound  = 3;
const float CapTriOut = 4;
const float CapTriIn  = 5;

// Colors a fragment based solely on either an input color or a texture.
vec4 coord_fragment(bool isUV,
                    sampler2D s,
                    vec4 clr,
                    vec2 uvs) {
  if (isUV) {
    return texture(s, uvs.st);
  } else {
    return clr;
  }
}

// Colors a fragment using Loop-Blinn curve rendering.
vec4 bez_fragment(bool isUV,
                  sampler2D s,
                  vec3 bz,
                  vec4 clr,
                  vec2 uvs) {
    vec2 p = bz.xy;
    // when cw is true, winding is clockwise and we're drawing outside the
    // curve.
    bool cw = bool(bz.z);
    // gradients
    vec2 px = dFdx(p);
    vec2 py = dFdy(p);
    // chain rule
    float fx = (2*p.x)*px.x - px.y;
    float fy = (2*p.x)*py.x - py.y;
    // signed distance
    float sd = (p.x*p.x - p.y) / sqrt(fx*fx + fy*fy);
    // linear alpha
    float alpha = 0.5 - sd;
    alpha = cw ? 1 - alpha : alpha;
    // find the resulting fragment color
    float a = 0;

    if (alpha > 1) {
        a = 1;
    } else if (alpha < 0) {
        discard;
    } else {
        // we are right on the boundary, interpolate the color intensity.
        a = alpha;
    }

    vec4 color = vec4(0);
    if (isUV) {
        color = texture(s, uvs.st);
    } else {
        color = clr;
    }
    return vec4(color.rgb, color.a * a);
}

// Renders a polyline cap fragment.
float capd(float type, float u, float v, float t ) {
    // None
    if ( type == CapNone) discard;
    // Round
    else if (type == CapRound) return sqrt(u*u+v*v);
    // Triangle out
    else if (type == CapTriOut) return (u+abs(v));
    // Triangle in
    else if (type == CapTriIn) return max(abs(v),(t+u-abs(v)));
    // Square
    else if (type == CapSquare) return max(u,v);
    // Butt
    else if (type == CapButt) return max(u+t,v);
    discard;
}

vec4 line_fragment(float thick,
                   float fthr,
                   float slen,
                   vec2 cp,
                   bool isUV,
                   sampler2D s,
                   vec4 clr,
                   vec2 bzuv,
                   vec2 uvs) {
    float u = bzuv.x;
    float v = bzuv.y;
    float l = slen;
    float dx = abs(min(u, u - l));
    float dy = abs(v);
    float d = dy;

    vec4 color = vec4(0);
    if (isUV) {
        color = texture(s, uvs.st);
    } else {
        color = clr;
    }

    float t = thick/2.0 - fthr;

    if (u < 0) {
        // fragment is in the start cap
        d = capd(cp.x, abs(u), dy, t);
    } else if (u > slen) {
        // fragment is in the end cap
        d = capd(cp.y, u - l, dy, t);
    }

    d -= t;
    if (d < 0.0) {
        return color;
    } else {
        d /= fthr;
        return vec4(color.rgb, exp(-d*d)*color.a);
    }
}

// Colors a fragment using two textures, one the input texture and one as the
// alpha masking texture.
vec4 mask_fragment(sampler2D main,
                   sampler2D mask,
                   vec2 uvs) {
    vec4 color = texture(main, uvs.st);
    vec4 msk  = texture(mask, uvs.st);
    return vec4(color.rgb, color.a * msk.a);
}

// Runs a color op on the fragment.
vec4 color_op_fragment(vec4 c, float a, vec4 m) {
  vec4 c1 = vec4(0);
  if (shouldColorReplace) {
    // Use a replacement color multiplied by the current red channel value.
    c1 = vec4(replaceColor.r, replaceColor.g, replaceColor.b, replaceColor.a * c.r) * m;
  } else {
    c1 = c * m;
  }
  return vec4(c1.rgb, c1.a * a);
}

void main() {
  vec4 out_color = vec4(0);
  switch (primitive) {
    case PrimTri:
      out_color = coord_fragment(hasUV, sampler, fcolor, fuv);
      break;
    case PrimBez:
      out_color = bez_fragment(hasUV, sampler, fbez, fcolor, fuv);
      break;
    case PrimLine: {
      out_color = line_fragment(thickness, feather, sumlength, cap, hasUV,
                                sampler, fcolor, fbezuv, fuv);
      break;
    }
    case PrimMask:
      out_color = mask_fragment(mainTex, maskTex, fuv);
      break;
    default:
      break;
  }

  fragColor = color_op_fragment(out_color, alpha, mult);
}