@threlte/extras
Version:
Utilities, abstractions and plugins for your Threlte apps
170 lines (143 loc) • 4.44 kB
JavaScript
import { revision } from '../../lib/revision';
export const vertexShader = /* glsl */ `
varying vec2 vUv;
varying vec2 vPos;
void main () {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
vUv = uv;
vPos = position.xy;
}
`;
export const fragmentShader = /* glsl */ `
// Majority from https://gist.github.com/statico/df64c5d167362ecf7b34fca0b1459a44
varying vec2 vUv;
varying vec2 vPos;
uniform vec2 scale;
uniform vec2 imageBounds;
uniform float resolution;
uniform vec3 color;
uniform sampler2D map;
uniform sampler2D colorProccessingTexture;
uniform float radius;
uniform float zoom;
uniform float alphaThreshold;
uniform float alphaSmoothing;
uniform float brightness;
uniform float contrast;
uniform float monochromeStrength;
uniform vec3 monochromeColor;
uniform float negative;
uniform vec3 hsl;
uniform float grayscale;
uniform float opacity;
uniform int colorProcessingEnabled;
uniform int colorProcessingTextureOverride;
vec2 aspect(vec2 size) {
return size / min(size.x, size.y);
}
// from https://iquilezles.org/articles/distfunctions
float udRoundBox(vec2 p, vec2 b, float r) {
return length(max(abs(p) - b + r, 0.0)) - r;
}
float hueToRgb(float p, float q, float t) {
if (t < 0.0f)
t += 1.0f;
if (t > 1.0f)
t -= 1.0f;
if (t < 1.0f / 6.0f)
return p + (q - p) * 6.0f * t;
if (t < 1.0f / 2.0f)
return q;
if (t < 2.0f / 3.0f)
return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
return p;
}
vec3 rgbToHsl(vec3 color) {
float max = max(max(color.r, color.g), color.b);
float min = min(min(color.r, color.g), color.b);
float h, s, l = (max + min) / 2.0f;
if (max == min) {
h = s = 0.0f;
} else {
float d = max - min;
s = l > 0.5f ? d / (2.0f - max - min) : d / (max + min);
if (max == color.r) {
h = (color.g - color.b) / d + (color.g < color.b ? 6.0f : 0.0f);
} else if (max == color.g) {
h = (color.b - color.r) / d + 2.0f;
} else if (max == color.b) {
h = (color.r - color.g) / d + 4.0f;
}
h /= 6.0f;
}
return vec3(h, s, l);
}
vec3 hslToRgb(vec3 hsl) {
float h = hsl.x;
float s = hsl.y;
float l = hsl.z;
float r, g, b;
if (s == 0.0f) {
r = g = b = l;
} else {
float q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;
float p = 2.0f * l - q;
r = hueToRgb(p, q, h + 1.0f / 3.0f);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1.0f / 3.0f);
}
return vec3(r, g, b);
}
vec3 monochrome(float x, vec3 col) {
return col * exp(4.0 * x - 1.0);
}
void processColors (inout vec4 colors) {
vec4 strength = vec4(1.0);
if (colorProcessingTextureOverride == 1) {
strength = texture2D(colorProccessingTexture, vUv);
float smoothedAlpha = smoothstep(1.0 - alphaThreshold - alphaSmoothing, 1.0 - alphaThreshold, strength.a + 0.0001);
colors.a *= smoothedAlpha;
if (gl_FragColor.a == 0.0) {
discard;
return;
}
}
// BRIGHTNESS
colors.rgb = max(colors.rgb + brightness, 0.0);
// CONTRAST
colors.rgb = max(((colors.rgb - 0.5) * max(contrast + 1.0, 0.0)) + 0.5, 0.0);
// HSL
vec3 hslColor = rgbToHsl(colors.rgb);
hslColor.x = mod(hslColor.x + hsl.x * strength.r ,1.0);
hslColor.y *= (1.0 + hsl.y * strength.g);
hslColor.z += hsl.z * strength.b;
colors.rgb = max(hslToRgb(hslColor), vec3(0.0));
// MONOCHROME
colors.rgb = mix(colors.rgb, monochrome(hslColor.z, monochromeColor), monochromeStrength);
}
void main() {
vec2 s = aspect(scale);
vec2 i = aspect(imageBounds);
float rs = s.x / s.y;
float ri = i.x / i.y;
vec2 new = rs < ri ? vec2(i.x * s.y / i.y, s.y) : vec2(s.x, i.y * s.x / i.x);
vec2 offset = (rs < ri ? vec2((new.x - s.x) / 2.0, 0.0) : vec2(0.0, (new.y - s.y) / 2.0)) / new;
vec2 uv = vUv * s / new + offset;
vec2 zUv = (uv - vec2(0.5, 0.5)) / zoom + vec2(0.5, 0.5);
vec2 res = vec2(scale * resolution);
vec2 halfRes = 0.5 * res;
float b = udRoundBox(vUv.xy * res - halfRes, halfRes, resolution * radius);
vec3 a = mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0), smoothstep(0.0, 1.0, b));
gl_FragColor = texture2D(map, zUv) * vec4(color, opacity * a);
if (colorProcessingEnabled == 1) {
processColors(gl_FragColor);
}
if (gl_FragColor.a == 0.0) {
discard;
}
gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(1.0) - gl_FragColor.rgb, negative);
}
`;