SFML 2.X GLSL - Shader wody resetuje się co 512px

SFML 2.X GLSL - Shader wody resetuje się co 512px

Wątek przeniesiony 2024-10-24 19:08 z Inne języki programowania przez flowCRANE.

tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
0

Witam. Znalazłem pewien Shader, który planuję użyć w swoim programie.
link
Problem polega na tym, że shader resetuje się co 512 px w pionie jak i poziomie.
Dlaczego tak się dzieje ?

RPG2D 143.png

Kod w SFML 2.X GLSL:

Kopiuj
uniform vec2 resolution;
uniform float time;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;
    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    vec2 uv = gl_TexCoord[0].xy / resolution.xy;
    float n = nestedNoise(uv * 25600.);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.
edytowany 6x, ostatnio: tBane
Spine
Fajnie jakbyś jeszcze jakiś screenshot dodał.
tBane
@Spine: ok. Już dodałem.
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
2

Woda jest jednokolorowa i shader nakłada na nią szum, prawda?
Każdy sprite wody to duży prostokąt, tak?

Tak na szybko, wydaje m się, że stosujesz shader na każdym prostokącie w jego lokalnej przestrzeni.

Gdyby shader korzystał z przestrzeni globalnej, to by generował szum bezszwowo, o ile jest w ten sposób napisany.


🕹️⌨️🖥️🖱️🎮
tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
1

@Spine eksperymentowałem z teksturami o różnym rozmiarze i zawsze jest taki sam efekt. Czyli to gdzieś po stronie shadera jest problem. A ja go niestety nie rozumiem, dlatego na forum się odezwałem.

No ale w Map Edytorze tego nie widać xD
screenshot-20241024151913.png


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.
edytowany 2x, ostatnio: tBane
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0
tBane napisał(a):

No ale w Map Edytorze tego nie widać xD

Ale chyba wiesz dlaczego :) ?
Szwy są zakrywane liniami.
Nie ma różnicy między 0x0 i 2x0, 0x1 i 2x1, itd...


🕹️⌨️🖥️🖱️🎮
DD
  • Rejestracja:6 miesięcy
  • Ostatnio:8 dni
  • Postów:22
0

Lepiej finalizuj to i przejdz do kolejnego kroku, bo przed toba jeszcze 1000 takich problemow. Lepiej nie zawieszaj sie na tym, lepiej wroc do tego typu problemow jak juz gra bedzie gotowa i potraktuj to jako szlifowanie efektu. Kazdy ci to powie

Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0

@Donsacz Donośny: Masz rację, ale nie do końca.

Może przy którymś problemie przejrzy na oczy, zobaczy z jaką prymitywną technologią ma do czynienia i przejdzie na coś współczesnego, co lepiej wspiera tworzenie gier, pracę nad shaderami itd...

Im szybciej, tym lepiej. Przesiadka z łopaty na koparkę naprawdę przyspieszy pracę.


🕹️⌨️🖥️🖱️🎮
edytowany 3x, ostatnio: Spine
DD
99xmarcin
  • Rejestracja:około 5 lat
  • Ostatnio:5 miesięcy
  • Postów:2420
0

A ta twoja textura to jakie ma wymiary?


Holy sh*t, with every month serenityos.org gets better & better...
tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
0

@99xmarcin 256x256


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.
99xmarcin
  • Rejestracja:około 5 lat
  • Ostatnio:5 miesięcy
  • Postów:2420
0

Szukał bym bug'a w linijce:

Kopiuj
vec2 uv = gl_TexCoord[0].xy / resolution.xy;

być może resolution źle ustawiasz i się "zawija"


Holy sh*t, with every month serenityos.org gets better & better...
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0

@99xmarcin: A ta linijka nie konwertuje po prostu uv z pikselowych wymiarów na zakres (0.0, 1.0)?

i potem float n = nestedNoise(uv * 25600.); mnoży jednostkowe uv przez 25600, bo np. viewport SFML jest ustawiony na bardzo duże liczby i w ten sposób zagęszczane są piksele szumu.

@tBane: Spróbuj rozwinąć linijkę vec2 uv = gl_TexCoord[0].xy / resolution.xy; w

Kopiuj
vec2 uv = abs((gl_TexCoord[0].xy / resolution.xy) + vec2(-0.5, -0.5));

Powinno to zmienić pattern w bardziej powtarzalny, ale za to będzie tileable.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
99xmarcin
Tak ale w zależności od tego jakie coords textury są na obiekcie to textura może się zawijać więc będzie 0 - 1.0 - 0.0 - 1.0 - 0.0 - 0.3
tBane
Wtedy psuje się shader. Staje się jednolitym kolorem.
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0

@tBane: Przerobiłem Twój shader, żeby działał w shadertoy.

1. Wklej ten kod zamiast shadera ze strony https://www.shadertoy.com/view/XdXBRH :

Kopiuj
float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;
    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + iTime);
    float y = fractalNoise(p - iTime);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    //vec2 uv = fragCoord / iResolution.xy;
    vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5));
    float n = nestedNoise(uv * 25.61);
    fragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

2. I daj play (lewy dolny róg pola tekstowego):

screenshot-20241024182955.png

3. Działa...

screenshot-20241024184241.png


🕹️⌨️🖥️🖱️🎮
edytowany 1x, ostatnio: Spine
Zobacz pozostałe 3 komentarze
tBane
nie wiadomo co było źle
obscurity
aha, no na tym playgroundzie jest tylko jeden tile tak? W każdym razie efekt tragiczny, wygląda jak fraktal albo obraz z kalejdoskopu. @tBane: może poszukaj po prostu innego shadera wody, ten i tak jest kiepski
Spine
Ten shader i tak nie pasuje do reszty grafiki ;)
tBane
Ale lepszego nie znalazłem :-/
Spine
Nowy shader najlepiej gdyby operował na world position. TexCoordy w ogóle można by pominąć. https://stackoverflow.com/questions/4899555/glsl-how-to-get-pixel-x-y-z-world-position
tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
0

@Spine ale po konwersji na SFML GLSL już nie działa:

screenshot-20241024190654.png

Kopiuj
uniform vec2 resolution;
uniform float time;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;

    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    //vec2 uv = gl_TexCoord[0].xy / resolution.xy;
    vec2 uv = abs((gl_TexCoord[0].xy / resolution.xy) + vec2(-0.5, -0.5));
    float n = nestedNoise(uv * 25.61);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

Poza tym vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5)); zmieniłbym na vec2 uv = abs((fragCoord / iResolution.xy);, bo wtedy nie ma lustrzanego poziomego odbicia


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.
edytowany 3x, ostatnio: tBane
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0
tBane napisał(a):

Poza tym vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5)); zmieniłbym na vec2 uv = abs((fragCoord / iResolution.xy);, bo wtedy nie ma lustrzanego poziomego odbicia

Jak usuniesz + vec2(-0.5, -0.5), to abs() jest zbędny.

To pewnie niewiele zmieni, ale mnożnika uv nie zwiększyłeś. W shadertoy zmniejszyłem go, bo szum miał zbyt duże zagęszczenie.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:4 minuty
  • Postów:8423
0
tBane napisał(a):

@Spine eksperymentowałem z teksturami o różnym rozmiarze i zawsze jest taki sam efekt. Czyli to gdzieś po stronie shadera jest problem.

Nie czytałem całego wątku, ale jak tekstury się powtarzają, to może ustawić wrapping mode na MIRRORED_REPEAT?
Nazewnictwa tutaj używam WebGL (które może być inne w tym API, z którego korzystasz), ale chodzi mi o to, co się ma dziać, jak pobierzesz wartość piksela spoza tekstury. Teraz widzę, że się powtarza:
Chodzi mi o coś takiego:
https://webglfundamentals.org/webgl/webgl-3d-textures-repeat-clamp.html

Taka pierwsza myśl, jednak ty tam robisz coś więcej niż tylko ustawiasz teksturę, więc możliwe, że problem jest w głębi shadera.
Chociaż w sumie taki efekt można by uzyskać również ręcznie.


edytowany 2x, ostatnio: LukeJL
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
0
LukeJL napisał(a):

Nie czytałem całego wątku, ale jak tekstury się powtarzają, to może ustawić wrapping mode na MIRRORED_REPEAT?

Wątpię aby to było cokolwiek innego niż CLAMP...
W końcu ma edytor, w którym można dodać wodę, więc każda woda to jest pojedynczy kafelek, czyli tutaj żaden REPEAT nie jest potrzebny, ani nie będzie wykorzystywany.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
1

No więc problem polegał na tym, że odnosiłem się do współrzędnych tekstury a nie do współrzędnych globalnych. (Prawdopodobnie domyślnie tekstura ma rozmiary 512x512). Rozwiązaniem jest stworzenie vertex shadera, dzięki któremu można otrzymać informację o współrzędnych pixela.

screenshot-20241025110353.png

Kopiuj
// vertex.frag

varying vec2 worldPos;

void main()
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
	worldPos = gl_ModelViewMatrix * gl_Vertex;
	gl_FrontColor = gl_Color;
}
Kopiuj
// water2.frag

uniform vec2 resolution;
uniform float time;
varying vec2 worldPos;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;

    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    vec2 uv = worldPos.xy * 0.05;
    float n = nestedNoise(uv);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.
edytowany 1x, ostatnio: tBane
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:około 3 godziny
  • Postów:6659
2
tBane napisał(a):

No więc problem polegał na tym, że odnosiłem się do współrzędnych tekstury a nie do współrzędnych globalnych.

Właśnie to napisałem w pierwszej odpowiedzi => SFML 2.X GLSL - Shader wody resetuje się co 512px

Tak na szybko, wydaje m się, że stosujesz shader na każdym prostokącie w jego lokalnej przestrzeni.

Gdyby shader korzystał z przestrzeni globalnej, to by generował szum bezszwowo, o ile jest w ten sposób napisany.


🕹️⌨️🖥️🖱️🎮
edytowany 1x, ostatnio: Spine
tBane
  • Rejestracja:ponad rok
  • Ostatnio:około 9 godzin
  • Lokalizacja:Poznań
  • Postów:312
2

@Spine po prostu nie zrozumiałem :-)


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.6.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.