🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
// rounded_corners.frag
// -----------------------------------------------------------------------------
// Maska zaokrąglonych rogów okna — pixel shader kompozytora (odpowiednik
// `shadow.frag`, ale zwracający jedynie kształt rogów).
//
// STATUS / PO CO TO JEST:
// W architekturze hybrydowego CSD to KLIENT rysuje zaokrąglone tło okna na
// przezroczystym buforze. Maska po stronie kompozytora nie jest więc potrzebna
// do poprawnego wyglądu. Ten shader jest gotowym narzędziem na dwa przyszłe
// scenariusze:
// 1) okno, które NIE zaokrągla rogów (aplikacja nie używająca toolkitu),
// 2) tryb SSD, gdy kompozytor sam rysuje ramkę okna.
//
// WAŻNE OGRANICZENIE: pixel shader nie może "wymazać" pikseli już narysowanych
// pod sobą (blending nie odejmuje). Aby przyciąć zawartość okna, trzeba je
// najpierw wyrenderować do tekstury i narysować przez `TextureShaderElement` —
// dlatego ten shader zwraca gotowy kształt, który można wykorzystać jako
// element tła/obramowania o poprawnym, zaokrąglonym konturze.
//
// Konwencja Smithaya: bez `#version`; dostępne v_coords, size, alpha.
// Dodatkowo: radius (promień zaokrąglenia), fill_color (RGBA, z alfą!), softness.
//
// PO CO `fill_color` jest `vec4`: przezroczystość „ducha” doklejania musi być
// częścią koloru, bo wbudowany `alpha` renderera to zawsze 1.0.
//
// `precision` musi być zadeklarowane samodzielnie — renderer dokleja tylko
// `#version 100`, a GLSL ES nie ma domyślnej precyzji dla `float`.
precision mediump float;
varying vec2 v_coords;
uniform vec2 size;
uniform float alpha;
uniform vec4 fill_color;
// Drugi kolor gradientu i siła mieszania po osi Y (0 = brak gradientu).
//
// PO CO: firmowy pasek tytułu PaganDE ma delikatny gradient (jaśniejsza góra),
// co odróżnia go od płaskich, generycznych dekoracji innych kompozytorów.
uniform vec4 fill_color2;
uniform float gradient_mix;
uniform float softness;
// Promienie zaokrąglenia KAŻDEGO rogu osobno: (lewy-górny, prawy-górny,
// prawy-dolny, lewy-dolny).
//
// PO CO per róg: pasek tytułu ma zaokrąglone TYLKO górne rogi (dolne muszą być
// proste, bo stykają się z treścią okna — inaczej zostałaby szczelina).
uniform vec4 radii;
// Wymiary SAMEgo KSZTAŁTU (nie obszaru elementu) oraz jego obrót w radianach.
//
// PO CO osobno od `size`: obszar elementu (uniform `size` od Smithaya) bywa
// większy niż kształt — tak rysujemy np. ukośne kreski ikony „X", gdzie
// prostokąt 3×17 obracamy o 45° w kwadratowym obszarze 20×20.
uniform vec2 rect_size;
uniform float angle;
// Odległość ze znakiem do prostokąta o zadanym promieniu jednego rogu.
float sd_rounded_rect(vec2 p, vec2 half_size, float r) {
vec2 d = abs(p) - (half_size - vec2(r));
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - r;
}
// Wybiera promień właściwy dla ćwiartki, w której leży punkt (y rośnie w dół).
float corner_radius(vec2 p) {
if (p.x >= 0.0) {
return p.y >= 0.0 ? radii.z : radii.y;
}
return p.y >= 0.0 ? radii.w : radii.x;
}
void main() {
// `v_coords` jest w UV [0..1]; skalujemy do pikseli i centrujemy.
vec2 p = (v_coords - vec2(0.5)) * size;
// Obrót punktu o `-angle` = obrót kształtu o `+angle`.
float c = cos(angle);
float s = sin(angle);
vec2 pr = vec2(c * p.x + s * p.y, -s * p.x + c * p.y);
// Promień wybieramy w układzie NIEobróconym (rogi prostokąta przed obrotem).
float r = corner_radius(p);
float dist = sd_rounded_rect(pr, rect_size * 0.5, r);
// smoothstep daje ~1px antyaliasing na krawędzi kształtu.
float mask = 1.0 - smoothstep(-softness, softness, dist);
// Gradient pionowy: `t` = 0 na górze, 1 na dole (mieszane wg `gradient_mix`).
float t = clamp(v_coords.y, 0.0, 1.0) * gradient_mix;
vec3 rgb = mix(fill_color.rgb, fill_color2.rgb, t);
float a = mix(fill_color.a, fill_color2.a, t);
gl_FragColor = vec4(rgb * mask, a * mask * alpha);
}