This content originally appeared on DEV Community and was authored by Sara
This blog explores how I implemented a simple shader that shows the illusion of a rug affected by the wind.
Lots of tutorials explaining how to do a waving flag shader but it’s always a 3D approach, so let’s just turn this into something that looks appropriate for a pixel art sprite.
Shader Components
Time Based Wave:
1st step is our typical time based wave that is going to be applied on the sprite.
- Control how fast it animates → Time * WaveSpeed
- Set how many waves appear → UV.x * WaveFrequency
- Use Sine wave to oscillate each pixel up&down
(Time * WaveSpeed) + (UV.X * WaveFrequency) → Sine Wave
To better understand it, I imagine if we paused time, we get too see each pixel at a different position on the sine curve and if we continue, all pixels shift position simulating the wave effect.
Secondary Wave for natural variation:
It is exactly the same as the first wave, except we could change the values of WaveSpeed(1.7) & WaveFrequency(2.2) a bit to add some natural variation to the wave and avoid a repetitive sine wave. Another thing added is the amplitude ratio, in my case (0.6) looked fairly good to avoid overpowering our main time based wave.
Wave Displacement:
Now we have got two waves and we need to combine them together
(Wave1+Wave2) * DampeningPower(0.004)
Pixel Snapping:
This is crucial step for my case since I want to keep the pixelated aesthetic to the sprite, without it the sprite will have very smooth wave effect which I don’t need in my case.
Floor(Wave Displacement * Pixel Density) / PixelDensity
- we round down using Floor to whole units to eliminate sub pixel positioning (which causes smoothing to the sprite)
- Divide by PixelDensity to convert back to UV space for texture sampling
First one uses pixel density of value 90, as we can see it’s way crispier than the other two, last one is very smooth which I don’t want in my current game so I’ve decided to go with a value of 300 which adds a little bit of pixelated aesthetic to it.
Combine all values to assign to our texture UV
Fake Light Effect
For adding a shadow effect I Just decided to add fake light and shadow wave on the fabric
we use the WaveDisplacement value for creating such effect.
- Apply absolute to the WaveDisplacement value to remove -ve values and just focus on the peaks and valleys of the wave
- Use Power to soften the values a little bit since it’s a shadow & light effect
- Multiply just to control the intensity
- Add to set minimum brightness
- Lastly we multiply it with the SampleTextrue2D RGBA
1st rug fake light values are set to zero which disables this part of the shader, 2nd simulates a little bit of dim light and shadow using low values for the wave, 3rd uses a higher LightMultiplay value.
This concludes my simple approach to animating rug sprites using a shader.
Thanks for reading! Tips and feedback are always welcome.
Pixel art by https://kenmi-art.itch.io/ & https://franuka.itch.io/
This content originally appeared on DEV Community and was authored by Sara