Import IKAR messenger client and server
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
#version 460 core
|
||||
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uRectOrigin;
|
||||
uniform vec2 uRectSize;
|
||||
uniform float uRadius;
|
||||
uniform float uSpread;
|
||||
uniform float uRefraction;
|
||||
uniform float uChroma;
|
||||
uniform float uSpecular;
|
||||
uniform vec4 uTint;
|
||||
uniform vec2 uLight;
|
||||
uniform float uTintFeather;
|
||||
uniform float uRimWidth;
|
||||
|
||||
uniform sampler2D uBackdrop;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
float roundedBoxSdf(vec2 p, vec2 halfSize, float radius) {
|
||||
vec2 q = abs(p) - halfSize + radius;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - radius;
|
||||
}
|
||||
|
||||
vec2 surfaceNormal(vec2 p, vec2 halfSize, float radius) {
|
||||
vec2 unit = vec2(1.0, 0.0);
|
||||
float dx = roundedBoxSdf(p + unit.xy, halfSize, radius) -
|
||||
roundedBoxSdf(p - unit.xy, halfSize, radius);
|
||||
float dy = roundedBoxSdf(p + unit.yx, halfSize, radius) -
|
||||
roundedBoxSdf(p - unit.yx, halfSize, radius);
|
||||
return normalize(vec2(dx, dy) + vec2(1e-6));
|
||||
}
|
||||
|
||||
const int TAPS = 5;
|
||||
|
||||
float displacement(float distance, float reach) {
|
||||
float bevel = 1.0 - clamp(-distance / reach, 0.0, 1.0);
|
||||
return uRefraction * bevel * bevel * (1.0 + bevel);
|
||||
}
|
||||
|
||||
vec3 sampleBackdrop(vec2 coord) {
|
||||
vec2 uv = coord / uSize;
|
||||
#ifdef IMPELLER_TARGET_OPENGLES
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
return texture(uBackdrop, clamp(uv, vec2(0.0), vec2(1.0))).rgb;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 fragCoord = FlutterFragCoord().xy;
|
||||
vec2 halfSize = uRectSize * 0.5;
|
||||
vec2 center = uRectOrigin + halfSize;
|
||||
vec2 p = fragCoord - center;
|
||||
|
||||
float radius = min(uRadius, min(halfSize.x, halfSize.y));
|
||||
float sd = roundedBoxSdf(p, halfSize, radius);
|
||||
|
||||
if (sd > 0.0) {
|
||||
fragColor = vec4(sampleBackdrop(fragCoord), 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 normal = surfaceNormal(p, halfSize, radius);
|
||||
float reach = max(uSpread * min(halfSize.x, halfSize.y), 1.0);
|
||||
float shift = displacement(sd, reach);
|
||||
float lens = shift / max(uRefraction, 1e-6);
|
||||
|
||||
float slope = displacement(sd + 1.0, reach) - displacement(sd - 1.0, reach);
|
||||
float footprint = clamp(abs(1.0 + slope * 0.5), 1.0, 24.0);
|
||||
float aberration = uChroma * lens;
|
||||
|
||||
vec3 refracted = vec3(0.0);
|
||||
for (int i = 0; i < TAPS; i++) {
|
||||
float offset = (float(i) / float(TAPS - 1) - 0.5) * footprint;
|
||||
vec2 base = fragCoord + normal * (shift + offset);
|
||||
if (aberration > 0.0) {
|
||||
refracted.r += sampleBackdrop(base + normal * shift * aberration).r;
|
||||
refracted.g += sampleBackdrop(base).g;
|
||||
refracted.b += sampleBackdrop(base - normal * shift * aberration).b;
|
||||
} else {
|
||||
refracted += sampleBackdrop(base);
|
||||
}
|
||||
}
|
||||
refracted /= float(TAPS);
|
||||
|
||||
float veil = smoothstep(0.0, 1.0, clamp(-sd / max(uTintFeather, 1.0), 0.0, 1.0));
|
||||
vec3 color = mix(refracted, uTint.rgb, uTint.a * veil);
|
||||
|
||||
vec2 light = normalize(uLight + vec2(1e-6));
|
||||
float facing = dot(normal, light);
|
||||
float rim = 1.0 - clamp(-sd / max(uRimWidth, 1.0), 0.0, 1.0);
|
||||
rim = rim * rim;
|
||||
float highlight = pow(max(facing, 0.0), 5.0) * rim * uSpecular;
|
||||
float shade = pow(max(-facing, 0.0), 4.0) * rim * uSpecular * 0.35;
|
||||
|
||||
color += vec3(highlight);
|
||||
color = mix(color, color * 0.72, shade);
|
||||
|
||||
fragColor = vec4(clamp(color, vec3(0.0), vec3(1.0)), 1.0);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#version 460 core
|
||||
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
precision highp float;
|
||||
|
||||
// #***! свёрл-дисторсия + радиально-взвешенное смешение цветов по опорным
|
||||
// точкам — тот же принцип, что даёт "живой" анимированный фон в Telegram
|
||||
// (portировано с их нативного generateGradient, image.cpp)
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform float uColorCount;
|
||||
uniform float uPhase;
|
||||
uniform float uProgress;
|
||||
uniform vec4 uColor0;
|
||||
uniform vec4 uColor1;
|
||||
uniform vec4 uColor2;
|
||||
uniform vec4 uColor3;
|
||||
uniform vec4 uColor4;
|
||||
uniform vec4 uColor5;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
const int POSITIONS_COUNT = 8;
|
||||
|
||||
int mod8(int v) {
|
||||
return v - (v / POSITIONS_COUNT) * POSITIONS_COUNT;
|
||||
}
|
||||
|
||||
vec2 rawPositionAt(int idx) {
|
||||
if (idx == 0) return vec2(0.80, 0.10);
|
||||
if (idx == 1) return vec2(0.60, 0.20);
|
||||
if (idx == 2) return vec2(0.35, 0.25);
|
||||
if (idx == 3) return vec2(0.25, 0.60);
|
||||
if (idx == 4) return vec2(0.20, 0.90);
|
||||
if (idx == 5) return vec2(0.40, 0.80);
|
||||
if (idx == 6) return vec2(0.65, 0.75);
|
||||
return vec2(0.75, 0.40);
|
||||
}
|
||||
|
||||
vec2 positionFor(int colorIndex, int phase) {
|
||||
int idx = mod8(colorIndex * 2 + phase);
|
||||
vec2 pos = rawPositionAt(idx);
|
||||
return vec2(pos.x, 1.0 - pos.y);
|
||||
}
|
||||
|
||||
vec4 colorAt(int i) {
|
||||
if (i == 0) return uColor0;
|
||||
if (i == 1) return uColor1;
|
||||
if (i == 2) return uColor2;
|
||||
if (i == 3) return uColor3;
|
||||
if (i == 4) return uColor4;
|
||||
return uColor5;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 fragCoord = FlutterFragCoord().xy;
|
||||
vec2 uv = fragCoord / uSize;
|
||||
|
||||
int colorsCount = int(uColorCount);
|
||||
if (colorsCount <= 1) {
|
||||
fragColor = colorAt(0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 centerDistance = uv - 0.5;
|
||||
float centerDist = length(centerDistance);
|
||||
float swirlFactor = 0.35 * centerDist;
|
||||
float theta = swirlFactor * swirlFactor * 0.8 * 8.0;
|
||||
float sinTheta = sin(theta);
|
||||
float cosTheta = cos(theta);
|
||||
|
||||
vec2 p = vec2(
|
||||
clamp(0.5 + centerDistance.x * cosTheta - centerDistance.y * sinTheta, 0.0, 1.0),
|
||||
clamp(0.5 + centerDistance.x * sinTheta + centerDistance.y * cosTheta, 0.0, 1.0)
|
||||
);
|
||||
|
||||
int phase = mod8(int(uPhase));
|
||||
int nextPhase = mod8(phase + 1);
|
||||
|
||||
float distanceSum = 0.0;
|
||||
vec3 accum = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (i >= colorsCount) break;
|
||||
vec2 curPos = positionFor(i, phase);
|
||||
vec2 nextPos = positionFor(i, nextPhase);
|
||||
vec2 pos = mix(curPos, nextPos, uProgress);
|
||||
|
||||
float d = max(0.0, 0.9 - distance(p, pos));
|
||||
d = d * d * d * d;
|
||||
distanceSum += d;
|
||||
accum += d * colorAt(i).rgb;
|
||||
}
|
||||
|
||||
vec3 color = distanceSum > 0.0001 ? accum / distanceSum : colorAt(0).rgb;
|
||||
fragColor = vec4(clamp(color, 0.0, 1.0), 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user