2D Fountain

Create a fountain effect based on particle systems.

This one requires a viewport to compute (see screenshots). First, we need a normal map of a ball. It’s pretty easy to find. Do some resize, and more importantly, add alpha/transparency. A lot. The idea is to use alpha channel to make a normal accumulation effect.

Then, use the computed sprite as a texture for your 2D particle systems. Try to configure your particle systems to simulate a fountain flow. For a better effect, use a first particle system with a size modulation over time to make particles bigger as they fall back. Use a second particle system with a slighty different configuration to simulate droplets.

Now the fun begins. As shown in the screenshot below, make those particle systems as children of a viewport. Place the viewport in a node to isolate it.

Finally, create a sprite with an ImageTexture as big as the viewport, and apply the shader coder displayed in this page. The important thing is to use the ViewportTexture to feed the refraction_map uniform.

Attach the following script on the root node in order to be able to edit shader properties on the fly and update the zoom uniform that will adjust the displacement/refraction depending on the zoom.


Shader code
shader_type canvas_item;

uniform sampler2D refraction_map;

uniform vec4 water_color : hint_color = vec4(0.1, 0.4, 0.9, 0.5);

uniform float displacement = 64.0;

uniform float zoom; // Used for sprite script. Don't edit this value in the inspector.

uniform float brightness : hint_range(0., 1.) = .3;

uniform float foam_strength : hint_range(1., 5.) = 2.;

void fragment() {
	vec4 refraction = texture(refraction_map, UV);
	vec4 refracted = texture(SCREEN_TEXTURE, SCREEN_UV + refraction.a * ((refraction.rg - vec2(0.5, 0.5)) / displacement) * zoom);
	vec4 minted = mix(refracted, water_color, (refraction.a * 0.5) * water_color.a);
	vec3 bright = clamp(minted.rgb + vec3(brightness), vec3(0.), vec3(1.));
	vec3 final = mix(minted.rgb, bright, step(0.01, refraction.a) * (1. - pow(refraction.a, foam_strength)));
	COLOR = vec4(final, 1.0);
2d, complex scene, foam, fountain, particle system, viewport, water
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from CasualGarageCoder

(Almost) Invisible Character

Chromatic Chaos Distortion

Ring of Power

Notify of

Inline Feedbacks
View all comments