Hi, this is a gif from my game.
I have this green water with a subtle glowing/moving effect. It might be hard to see but some of the pixels gradually become brighter/darker and move a little bit to the left/right over time. Right now I have 4 different water tiles with each one having 4 frames of animation to get this effect. Is it possible to achieve something like this using a shader?
How to achieve this type of water effect through a shader?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 2
- Joined: Wed Jan 02, 2019 7:44 am
Re: How to achieve this type of water effect through a shader?
I totally think it is.
Actually i'm not totally familiar with shaders and canvases in love but my wild guess is to draw the water tiles in a separate canvas (you might need to add a stencyl) and apply a shader that get a vector of points contained in the water tiles as an extern input and that change their color using sin(u_time)
Actually i'm not totally familiar with shaders and canvases in love but my wild guess is to draw the water tiles in a separate canvas (you might need to add a stencyl) and apply a shader that get a vector of points contained in the water tiles as an extern input and that change their color using sin(u_time)
Re: How to achieve this type of water effect through a shader?
The closest I can think of is to use an image for the spots and use a shader for animation only.
It would consist of three B/W images with black background and the spots that flash in white, and combine them as one single image, with the R channel being one of the B/W images, the G channel being another, and the B channel being another. Maybe you can use the A channel for the same purpose as well.
All the spots in the R channel would flash at the same time. So would all the spots in the G channel and all the spots in the B channel.
In each frame, you would send the shader a time parameter, and the shader would draw the image with the colours that it has built in, using the image for its data only, not directly as colour information. A sine function, multiplied by the corresponding pixel of the image, would add or remove some intensity for the colour in the respective channel. The R, G, and B channel's sine waves would be separated by 120° (or by 90° if you're using R, G, B, A).
The movement could perhaps also be implemented in the shader, but maybe it's best to do it by moving the image a bit when drawing.
In pseudocode:
Remember that the shader works in radians, though.
It would consist of three B/W images with black background and the spots that flash in white, and combine them as one single image, with the R channel being one of the B/W images, the G channel being another, and the B channel being another. Maybe you can use the A channel for the same purpose as well.
All the spots in the R channel would flash at the same time. So would all the spots in the G channel and all the spots in the B channel.
In each frame, you would send the shader a time parameter, and the shader would draw the image with the colours that it has built in, using the image for its data only, not directly as colour information. A sine function, multiplied by the corresponding pixel of the image, would add or remove some intensity for the colour in the respective channel. The R, G, and B channel's sine waves would be separated by 120° (or by 90° if you're using R, G, B, A).
The movement could perhaps also be implemented in the shader, but maybe it's best to do it by moving the image a bit when drawing.
In pseudocode:
Code: Select all
c = pixel from the image
b = base colour (the background green)
m = colour when the spot is at its maximum bright
t = time
i = max(0, sin(t)) * c.r // contribution of the R channel
i = i + max(0, sin(t + 120°)) * c.g // contribution of the G channel
i = i + max(0, sin(t + 240°)) * c.b // contribution of the B channel
return colour * mix(b, m, i)
Re: How to achieve this type of water effect through a shader?
Here's an implementation of the above idea:
I tweaked some parameters until they worked reasonably, namely the range of the sine wave and the square root.
The image I used uses only three channels. I made it with gimp, using filters>noise>hurl, tools>color tools>threshold, filters>blur>gaussian blur, colors>auto>equalize, colors>auto>normalize (all these three times with different hurl seeds) and colors>components>compose (to join the RGBs). It's included in the attached love file.
And here's the result:
I may use this for T2R
Code: Select all
local lg, lt, le = love.graphics, love.timer, love.event
local shader = lg.newShader[[
extern vec4 base;
extern vec4 maxc;
extern number t;
vec4 effect(vec4 col, Image tex, vec2 imgpos, vec2 scrpos)
{
vec4 c = Texel(tex, imgpos);
float i = (sin(t) + 1.) / 2. * c.r;
i += (sin(t + 2.0943951) + 1.) / 2. * c.g;
i += (sin(t - 2.0943951) + 1.) / 2. * c.b;
i = clamp(i, 0., 1.);
return col * mix(base, maxc, sqrt(i));
}
]]
local rgb = {0,0,1,1}
shader:send('base', rgb)
rgb[1] = 1
rgb[2] = 1
shader:send('maxc', rgb)
local img = lg.newImage('lake-effect.png')
function love.draw()
shader:send('t', (lt.getTime() % (2* math.pi)) * 7)
lg.setShader(shader)
lg.draw(img)
lg.setShader()
end
function love.keypressed(k)
return k == "escape" and le.quit()
end
The image I used uses only three channels. I made it with gimp, using filters>noise>hurl, tools>color tools>threshold, filters>blur>gaussian blur, colors>auto>equalize, colors>auto>normalize (all these three times with different hurl seeds) and colors>components>compose (to join the RGBs). It's included in the attached love file.
And here's the result:
I may use this for T2R
- Attachments
-
- lake-effect.love
- (10.26 KiB) Downloaded 208 times
Who is online
Users browsing this forum: Google [Bot] and 10 guests