tBane Temat założony przez niniejszego użytkownika |
[SFML GLSL] Shader Wody » 2024-10-24 12:20:59 Witam. Znalazłem pewien Shader, który mi się spodobał. https://www.shadertoy.com/view/Mt2SzRChciałbym go przepisać na SFML 2.X GLSL. Skopiowałem Shader i zmieniłem kilka rzeczy - tak żeby SFML 2.X nie wyrzucał błędu. Ostatecznie Shader nie działa tak jak powinien. Czy to ja gdzieś błąd zrobiłem czy faktycznie Shader nie działa tak jak pokazuje na shadertoy ? 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 * 6.); gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.); }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-24 12:26:16 Gdy ustawiłem float n = nestedNoise(uv * 25600.); to wtedy woda zaczęła przypominać tą z https://www.shadertoy.com. Gdzie zrobiłem błąd ? Ale dostrzełem błąd - co dwa chunki(512px) shader tak jakby się resetuje. Wie ktoś z jakiego powodu nie ma płynnego przejścia i skąd to wywnioskować ? |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-24 13:00:50 Eksperymentowałem z różnymi wielkościami tekstury i nic to nie dało :-/ |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-24 19:21:44 Jak na razie mój Shader prezentuje się następująco: shader->setUniform( "time", currentTime.asSeconds() ); sf::Vector2f resolution( 1280, 720 ); shader->setUniform( "resolution", resolution );
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.); }
|
|
pekfos |
» 2024-10-24 22:05:54 vec2 uv = gl_TexCoord[0].xy / resolution.xy; float n = nestedNoise(uv * 25600); Pewny jesteś użycia tu współrzędnych tekstury? W zasadzie przerobiłem tylko to i wydaje się działać. #include <SFML/Graphics.hpp> #include <cmath>
const std::string VertexShader = R"(
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;
}
)";
const std::string WaterFragmentShader = R"(
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.);
}
)";
int main() { int tilesx = 128, tilesy = 96; sf::RenderWindow okno( sf::VideoMode( tilesx * 10, tilesy * 10 ), "Kurs SFML 2.0 - http://cpp0x.pl" ); sf::Image img; img.create( 10, 10 ); for( int i = 0; i < img.getSize().x; ++i ) for( int j = 0; j < img.getSize().y; ++j ) img.setPixel( i, j, sf::Color( i * 25, j * 25, 0 ) ); sf::Texture tex; tex.loadFromImage( img ); sf::Shader shader; if( !shader.loadFromMemory( VertexShader, WaterFragmentShader ) ) return 1; sf::Clock stoper; while( okno.isOpen() ) { sf::Event event; while( okno.pollEvent( event ) ) { if( event.type == sf::Event::Closed ) okno.close(); if( event.type == sf::Event::Resized ) { tilesx = event.size.width / 10; tilesy = event.size.height / 10; auto view = okno.getView(); view.setSize( event.size.width, event.size.height ); view.setCenter( event.size.width / 2, event.size.height / 2 ); okno.setView( view ); } } okno.clear(); sf::VertexArray va( sf::Quads, tilesx * tilesy * 4 ); for( int i = 0, k = 0; i < tilesx; ++i ) for( int j = 0; j < tilesy; ++j ) { sf::Vector2f pos( i * 10, j * 10 ), off( 0, 0 ); va[ k ].position = pos + off; va[ k ].texCoords = off; k++; off.x = 10; va[ k ].position = pos + off; va[ k ].texCoords = off; k++; off.y = 10; va[ k ].position = pos + off; va[ k ].texCoords = off; k++; off.x = 0; va[ k ].position = pos + off; va[ k ].texCoords = off; k++; } shader.setUniform( "time", stoper.getElapsedTime().asSeconds() ); shader.setUniform( "resolution", sf::Vector2f( tilesx * 10, tilesy * 10 ) ); sf::RenderStates rs; rs.texture = & tex; rs.shader = & shader; okno.draw( va, rs ); okno.display(); } } Rozdzielczość była w oryginale używana do uzyskania znormalizowanego uv. Tu dałem współrzędne świata jako uv i jak na razie nie widzę problemów. Możesz rozciągnąć okno żeby sprawdzić większą albo mniejszą mapę. Kafelki mają 10x10, jak wykomentujesz użycie shadera w rs to będzie widać strukturę mapy. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-25 11:22:41 Ok. Rozumiem. Dzięki za pomoc. Jeszcze dodałem efekt pikselizacji. void main() { vec2 coords = worldPos.xy / resolution; float pixelFactor = 0.0078125; vec2 pixelCoord = floor( coords / pixelFactor ) * pixelFactor; float n = nestedNoise( pixelCoord * 25.60 ); vec3 color = mix( vec3( .4, .6, 1. ), vec3( .1, .2, 1. ), n ); vec3 darkcolor = color * 0.7; gl_FragColor = vec4( darkcolor, 1. ); }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-11-01 19:49:46 Mam jeszcze jeden BUG polegający na tym, że gdy przemieszczam się po mapie to tak samo przemieszcza się "woda w palecie". Chciałbym aby była renderowana "względem palety" a nie "względem świata". // water2.frag uniform sampler2D texture; 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() { vec4 texcolor = texture2D(texture, gl_TexCoord[0].xy); if(texcolor.x == 127./255. && texcolor.y == 127./255. && texcolor.z == 127./255. && texcolor.w == 1.0) { vec2 coords = worldPos.xy/resolution; float pixelationFactor = 0.00390625; vec2 pixelCoord = floor(coords / pixelationFactor) * pixelationFactor; float n = nestedNoise(pixelCoord * 25.60); vec3 color = mix(vec3(.4, .6, 1.), vec3(.05, .1, 1.), n); vec3 darkcolor = color * 0.7; gl_FragColor = vec4(darkcolor, 1.); }else{ gl_FragColor = texcolor; } } |
|
pekfos |
» 2024-11-01 22:11:39 Tak samo wyświetlasz wodę w obu przypadkach, więc działa tak samo. Możesz dodać parametr do shadera by rozróżnić te przypadki. |
|
« 1 » 2 |