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:3 minuty
  • 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 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:3 minuty
  • 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 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:7 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 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:3 minuty
  • 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 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 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
obscurity
czyli co było źle?
obscurity
po odkomentowaniu vec2 uv = fragCoord / iResolution.xy też działa i znacznie lepiej wygląda
Spine
Ja wiem, ale abs jest użyty, aby efekt był bezszwowy na przylegających do siebie tilesach wody.
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:3 minuty
  • 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 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:43 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 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:3 minuty
  • 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 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:3 minuty
  • 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.