Outline - Shader generujący obrys wokół kształtów na zadanym tle
Ostatnio zmodyfikowano wczoraj o godz. 19:04
tBane Temat założony przez niniejszego użytkownika |
Outline - Shader generujący obrys wokół kształtów na zadanym tle » 2025-11-05 17:40:59 Witam. Poszukuje shadera do generowania outline na teksturze w taki sposób, że:-outlineColor - określa kolor obrysu -outlineWidth - określa szerokość obrysu -backgroundColor - określa kolor na którym jest generowany obrys -outline jest generowany "na zewnątrz" Mam algorytm od ChataGPT ale na obrys "do wewnątrz":std::string outline_shader_source = R"(
uniform sampler2D texture;
uniform vec2 texelSize; // 1/rozmiar tekstury
uniform float width; // 0..8 (promień w px)
uniform vec4 backgroundColor; // kolor tła
uniform vec4 outlineColor; // kolor obrysu (rgb) + siła a (0..1)
uniform float threshold; // tolerancja dopasowania koloru tła (np. 0.02..0.1)
float colorDistance(vec3 a, vec3 b) { return length(a - b); }
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec4 base = texture2D(texture, uv);
// bieżący piksel to tło?
float isBg = step(colorDistance(base.rgb, backgroundColor.rgb), threshold);
// promień (zaokrąglony, ograniczony do 8)
int r = int(ceil(clamp(width, 0.0, 8.0)));
// czy w sąsiedztwie leży cokolwiek NIE będącego tłem?
float hasNonBgNeighbor = 0.0;
for (int dy = -8; dy <= 8; ++dy) {
for (int dx = -8; dx <= 8; ++dx) {
if (abs(dx) > r || abs(dy) > r) continue;
if (dx*dx + dy*dy > r*r) continue; // koło
if (dx == 0 && dy == 0) continue; // pomijamy siebie
vec2 o = vec2(float(dx), float(dy)) * texelSize;
vec3 c = texture2D(texture, uv + o).rgb;
float isBgSample = step(colorDistance(c, backgroundColor.rgb), threshold);
hasNonBgNeighbor = max(hasNonBgNeighbor, 1.0 - isBgSample);
}
}
// obrys powstaje TYLKO na pikselach tła stykających się z obiektem
float edge = isBg * hasNonBgNeighbor;
// kolorujemy piksele tła tam, gdzie edge==1, reszta bez zmian
vec3 rgbOut = mix(base.rgb, outlineColor.rgb, edge * outlineColor.a);
float aOut = base.a; // nie ruszamy alfy
gl_FragColor = vec4(rgbOut, aOut);
}
)";
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-11-05 17:59:57 Dobra. Udało się. Oto dany shader generujący outline :-)  std::string outline_shader_source = R"(
uniform sampler2D u_tex;
uniform vec2 texelSize; // 1.0 / textureSize
uniform float outlineWidth; // 0..8 px
uniform vec4 backgroundColor; // kolor tła (color key)
uniform vec4 outlineColor; // kolor obrysu (rgb) + siła a [0..1]
uniform float threshold; // tolerancja podobieństwa do tła (0.02..0.08)
float colorDistance(vec3 a, vec3 b) { return length(a - b); }
void main() {
vec2 uv = gl_TexCoord[0].xy;
vec4 base = texture2D(u_tex, uv);
// bieżący piksel to tło?
float isBg = step(colorDistance(base.rgb, backgroundColor.rgb), threshold);
// promień próbkowania (max 8)
int r = int(ceil(clamp(outlineWidth, 0.0, 8.0)));
// wykryj, czy w sąsiedztwie jest piksel NIE-będący tłem (czyli „obiekt”)
float hasNonBgNeighbor = 0.0;
if (r > 0) {
for (int dy = -outlineWidth; dy <= outlineWidth; dy++) {
for (int dx = -outlineWidth; dx <= outlineWidth; dx++) {
if (abs(dx) > r || abs(dy) > r) continue;
if (dx*dx + dy*dy > r*r) continue; // koło
if (dx == 0 && dy == 0) continue; // pomijamy siebie
vec2 o = vec2(float(dx), float(dy)) * texelSize;
vec3 c = texture2D(u_tex, uv + o).rgb;
float isBgSample = step(colorDistance(c, backgroundColor.rgb), threshold);
hasNonBgNeighbor = max(hasNonBgNeighbor, 1.0 - isBgSample);
}
}
}
// malujemy TYLKO na pikselach tła stykających się z obiektem (zewnętrzny obrys)
float edge = isBg * hasNonBgNeighbor;
// kolorujemy tło na krawędzi; piksele obiektu zostają nietknięte; alfa bez zmian
vec3 rgbOut = mix(base.rgb, outlineColor.rgb, edge * outlineColor.a);
float aOut = base.a;
gl_FragColor = vec4(rgbOut, aOut);
}
)";
|
|
| « 1 » |