Page 1 of 2
Trying to create a "water" shader
Posted: Sun Jan 29, 2017 5:06 am
by Jasoco
I'm a bit stumped on how to go about this. Basically I want to create a water effect shader for the reflections in my game. But I can't figure out how to just shift a row of pixels.
I mean you know how it ripples. Not quite a sine wave pattern but more an abnormal pattern of jaggy offsets moving in a smooth wave pattern. But I just don't know how I would shift a row of pixels or something.
I mean right now I just have this pretty looking thing:
It's not that big a deal. I'm drawing each reflectable entity onto a separate field that gets placed below the world and the water is a transparent blue texture. But I'd like to do something cool with the reflection layer just to make it look neater.
Re: Trying to create a "water" shader
Posted: Sun Jan 29, 2017 9:31 am
by raidho36
Use timer external variable and UV position of the pixel, sample by coordinates shifted sideways by sine function that takes timer as an input and vertical pixel coordinate as a static offset. Just get sinewave cycle to be smaller than one pixel. Then it will still be cyclical while not appearing as sinewave visually.
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 12:25 am
by alloyed
Here's a writeup that's been sitting in my bookmarks:
https://forums.tigsource.com/index.php? ... msg1104986
It's pretty similar to what raidho suggested, except instead of using a sine wave to decide displacement it looks at a texture, and then it does some perspective correction stuff that shouldn't matter for a top down game. So you can probably safely stop at step 1 :p
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 7:17 am
by ivan
How about a simple solution using blend modes?
All you'd need is an animated ripples texture (seamlessly tiled).
First you draw the blue backdrop, then you draw the reflections and finally you draw the ripples on top.
The ripples texture needs to be noisy, possibly using additive blending - which will make reflected objects appear fuzzy and washed out.
With a little bit of tweaking I think you can get a decent-looking water effect.
I've used a similar approach for the analog filters in
this game.
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 8:37 pm
by Jasoco
All I really want is to give a slight waving effect to the reflection layer. I just don't know what code to use in the shader to grab a pixel at an offset instead of the current one.
I'm reading that Kingdom writeup alloyed posted above and maybe it'll give me some ideas. But I don't know what code to use. Shaders are so.. not Lua at all. But I find them intriguing. I even read through the entire "Share a shader" thread and couldn't really find anything that helps give me simple code to displace a pixel.
Small chance I might not even keep reflections. I don't know yet. I'm experimenting. But right now my method requires that I draw a bunch of images a second time. Some entities can just use the same images flipped upside down, but others I need to actually draw the reflected version. Like the pots (Seen above) which can't just be mirrored since then it would look stupid as heck, so I drew a quick "underside" style view to use for them. And walls will need to be drawn without the "top" part of the wall since obviously you wouldn't be able to see the top of the wall in the reflection. Same with the waterfall which would need a separate version without the top of the waterfall. Though I would like to figure out a way to just fade the reflection after 24 or 32 pixels so I don't have to worry about tall things.
Still a work in progress and an experiment that I might not even use. Though I do plan on making ice floors eventually and would like to have reflections there. Maybe also shiny tile floors for fancy buildings.
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 9:01 pm
by veethree
I just don't know what code to use in the shader to grab a pixel at an offset instead of the current one
I recently implemented
conway's game of life in glsl, And game of life logic requires grabbing adjacent pixels.
I used something like this
Code: Select all
vec4 Pixel = Texel(tex, vec2(tc.x, tc.y - (1.0 / size.y)));
"Pixel" would be the pixel above the current one. And size is a vec2 with the width/height of the window.
Not sure if this helps, I may have misunderstood what you mean by "grab a pixel"
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 10:32 pm
by Jasoco
Well I don't know what I'm doing wrong. What am I missing here?
It's only grabbing like one line of pixels or something. I don't know because it doesn't look right at all. (The blackness is because there's only a water underlay tile under the water tiles. The black is regular ground, or rather transparency on the canvas since the ground doesn't draw an underlay.)
This is my shader so far:
Code: Select all
extern vec2 size;
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){
vec4 pixel = Texel(texture, vec2(texture_coords.x - (1.0 / size.x)), texture_coords.y);
return pixel;
}
Code: Select all
lgr.setShader(waterShader)
waterShader:send("size", {RENDERWIDTH, RENDERHEIGHT})
lgr.setColor(255,255,255)
lgr.draw(self.reflectionCanvas, 0, 0)
lgr.setShader()
RENDERWIDTH, RENDERHEIGHT are the size of the canvas itself. It doesn't seem to matter at all if I replace them with love.graphics.getWidth() and getHeight(). I get the same result.
Where am I going wrong?
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 10:39 pm
by Nixola
There's a subtle mistake in one line:
Code: Select all
vec4 pixel = Texel(texture, vec2(texture_coords.x - (1.0 / size.x)), texture_coords.y);
//should be
vec4 pixel = Texel(texture, vec2(texture_coords.x - (1.0 / size.x), texture_coords.y));
Re: Trying to create a "water" shader
Posted: Mon Jan 30, 2017 11:48 pm
by Jasoco
Haha, that works. Or at least I now have a shifted pixel so it's a starting point. I'm surprised and not surprised because I should have seen it coming as I remember moving that piece of code from the Y part to the X part and grabbing the whole thing. Funny, I guess I expected it to error me out if it was typed wrong instead of just accepting it and compiling it as is.
Okay, now to get to work figuring out how to make it look neat.
Re: Trying to create a "water" shader
Posted: Tue Jan 31, 2017 12:56 am
by raidho36
Code: Select all
extern time;
vec4 pixel = Texel(texture, vec2(texture_coords.x - sin(time + texture_coords.y * 10), texture_coords.y));