Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 3.0.2] Kolor Przeźroczystości w Shaderze

Ostatnio zmodyfikowano dzisiaj: 6h » 53 min
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[SFML 3.0.2] Kolor Przeźroczystości w Shaderze
» 2026-03-14 13:02:02
Cześć. Próbuję napisać shader do renderowania obrazu.
Obraz ma działać tak, że użytkownik podaje kolor przeźroczystości.
I jeżeli obraz ma piksel taki jak kolor przezroczystości. To kolor ma być przezroczysty.
Wydaje się proste ale mi nie działa :-/ Pomożecie?
Maska ma wartości następujące - biały - rysuj pixel, inny kolor nie rysuj piksela.


C/C++
std::string mask_shader_source = R"( uniform sampler2D texture; uniform sampler2D mask; uniform vec4 alphaColor; void main() { vec2 uv = gl_TexCoord[0].xy; vec4 c = texture2D(texture, uv); float alpha = (c.r == alphaColor.r && c.g == alphaColor.g && c.b == alphaColor && c.a == alphaColor) ? 0.0 : texture2D(mask, uv).a; gl_FragColor = vec4(c.rgb, c.a * alpha); } )";
P-183920
DejaVu
» 2026-03-14 13:23:05
Odpowiedź wygenerowana przez GLM 5 Thinking:
Cześć! Przejrzałem Twój kod shadera i widzę w nim błąd składniowy, który najprawdopodobniej powoduje, że shader w ogóle się nie kompiluje lub działa niepoprawnie.

Główny błąd
W warunku if (w operatorze trójelementowym) próbujesz porównać pojedynczy kanał koloru (typ float, np. c.b) do całego wektora koloru (typ vec4, czyli alphaColor).

Masz tam:
c.b == alphaColor
oraz
c.a == alphaColor

To tak, jakbyś próbował porównać jedną liczbę do czterech liczb naraz. Kompilator GLSL tego nie przepuści (lub zwróci błąd, który SFML może ignorować w domyślnej konfiguracji, zostawiając czarny ekran).

Musisz porównywać float z float, czyli odwołać się do konkretnych składowych wektora alphaColor (używając .r, .g, .b, .a lub .x, .y, .z, .w).

Poprawiony kod (pod względem składni)
C/C++
std::string mask_shader_source = R"( uniform sampler2D texture; uniform sampler2D mask; uniform vec4 alphaColor; void main() { vec2 uv = gl_TexCoord[0].xy; vec4 c = texture2D(texture, uv); // POPRAWKA: Dodano .b i .a do alphaColor // Zwróć uwagę na alphaColor.b oraz alphaColor.a float alpha = (c.r == alphaColor.r && c.g == alphaColor.g && c.b == alphaColor.b && c.a == alphaColor.a) ? 0.0 : texture2D(mask, uv).a; gl_FragColor = vec4(c.rgb, c.a * alpha); } )";
Ważna uwaga dotycząca precyzji (Floating Point)
Używanie operatora == (równości) na liczbach zmiennoprzecinkowych (float) w shaderach jest bardzo ryzykowne. Nawet minimalny błąd zaokrąglenia (rzędu 0.0001) spowoduje, że kolory nie będą równe, a piksel nie stanie się przezroczysty.

Zamiast sprawdzać c.r == alphaColor.r, znacznie lepiej jest sprawdzić, czy różnica między kolorami jest "wystarczająco mała" (tzw. epsilon).

Oto bezpieczniejsza i bardziej profesjonalna wersja tego shadera:

C/C++
std::string mask_shader_source = R"( uniform sampler2D texture; uniform sampler2D mask; uniform vec4 alphaColor; void main() { vec2 uv = gl_TexCoord[0].xy; vec4 c = texture2D(texture, uv); // Obliczamy różnicę wektorów. // Funkcja distance zwraca odległość (długość wektora różnicy). // Jeśli jest mniejsza niż 0.01 (czyli 1% różnicy), uznajemy, że kolory są równe. float dist = distance(c.rgb, alphaColor.rgb); // Sprawdzamy też kanał alfa (jeśli jest potrzebny) bool isTransparent = (dist < 0.01) && (abs(c.a - alphaColor.a) < 0.01); float alpha = isTransparent ? 0.0 : texture2D(mask, uv).a; gl_FragColor = vec4(c.rgb, c.a * alpha); } )";
Daj znać, czy po poprawieniu odwołań do .b i .a zaczęło działać!
P-183921
tBane
Temat założony przez niniejszego użytkownika
» 2026-03-14 13:32:54
Nie działa :-/ Maska nie przechowuje przeźroczystości tylko ma biały kolor dla piksela który ma być rysowany i kolor przeźroczysty dla piksela który nie ma być rysowany.
P-183922
tBane
Temat założony przez niniejszego użytkownika
» 2026-03-14 13:51:14
P-183923
tBane
Temat założony przez niniejszego użytkownika
» 2026-03-14 14:20:17
Dobra. Działa :-)

C/C++
uniform sampler2D texture;
uniform sampler2D mask;
uniform vec4 alphaColor;

void main() {
   
vec2 uv = gl_TexCoord[ 0 ].xy;
   
   
if( texture2D( mask, uv ) == vec4( 1.0, 1.0, 1.0, 1.0 ) ) {
       
vec4 c = texture2D( texture, uv );
       
       
if( c == alphaColor )
           
 gl_FragColor = vec4( 0, 0, 0, 0 );
       
else
           
 gl_FragColor = c;
       
   
} else {
       
gl_FragColor = vec4( 0, 0, 0, 0 );
   
}
}
P-183924
« 1 »
  Strona 1 z 1