Tiler (pseudo splatter)

A shader that repeats an image at different sizes and positions, similar to Material Maker’s Tiler node.

Everything is done without using loops, making it a fast method for drawing many variations of the same texture.

You can find the full example on my github

For more details, please watch the video on my youtube channel (its AI dubbed).

Hope you’ll like ​🤓​

 

Shader code
shader_type canvas_item;

// enable/disable rotation
#define USE_ROTATION 1

// enable/disable color modulation
#define USE_COLOR_MODULATION 1

uniform float g_random_seed = 0.0;
uniform vec2 g_grid_size = vec2(16.0, 9.0); // x=cols, y=rows (16 and 9 are good values for a full screen rect in 16:9 aspect ratio display)
uniform vec2 g_cell_offset = vec2(0.0, 0.0);
uniform vec2 g_speed = vec2(0.0, 0.0);
uniform float g_draw_size_min : hint_range(0.0, 1.0) = 0.1; // value between 0 and 1 (avoid 0)
uniform float g_draw_size_max : hint_range(0.0, 1.0) = 0.4; // value between 0 and 1 (avoid 0)
uniform sampler2D tex_draw;

#if USE_COLOR_MODULATION
uniform vec4 g_color_a : source_color = vec4(1.0, 1.0, 1.0, 0.0);
uniform vec4 g_color_b : source_color = vec4(1.0, 1.0, 1.0, 1.0);
#endif

#if USE_ROTATION
const float INV_SQRT2 = 0.70710678118;
group_uniforms Rotation;
uniform float g_rot_global_speed = 1.0;
uniform float g_rot_min_speed : hint_range(0.0, 1.0) = 0.1; // value between 0 and 1
uniform float g_rot_max_speed : hint_range(0.0, 1.0) = 1.0; // value between 0 and 1
#endif

// returns a pseudo random number 
float random(vec2 xy) {
    return fract(sin(dot(xy, vec2(12.9898, 78.233))) * 43758.5453);
}

#if USE_ROTATION
// taken from godotshaders :)
vec2 rotate(vec2 uv, vec2 pivot, float angle)
{
	mat2 rotation = mat2(vec2(sin(angle), -cos(angle)),
						vec2(cos(angle), sin(angle)));
	
	uv -= pivot;
	uv = uv * rotation;
	uv += pivot;
	return uv;
}
#endif

vec4 draw_tile(vec4 default_color, vec2 local_uv, vec2 center, float size, float speed, vec4 color)
{	
	vec2 tile_uv_map = (local_uv - center) / size + 0.5;
#if USE_ROTATION	
	tile_uv_map = rotate(tile_uv_map, vec2(0.5), TIME * speed);
#endif

    if (
        tile_uv_map.x < 0.0 || tile_uv_map.x > 1.0 ||
        tile_uv_map.y < 0.0 || tile_uv_map.y > 1.0
    ) {
        return default_color;
    }	
		
	vec4 s = texture(tex_draw, tile_uv_map);
	return s * color;
}

vec4 draw_layer(
	vec4 default_color, 
	float random_seed,	
	vec2 uv, 
	vec2 grid_size, 
	vec2 speed,
	vec2 cell_offset,
	float draw_size_min,
	float draw_size_max
#if USE_ROTATION	
	,float rot_global_speed
	,float rot_min_speed
	,float rot_max_speed
#endif	
#if USE_COLOR_MODULATION
	,vec4 color_a
	,vec4 color_b
#endif
) {
    vec2 grid_uv = (uv * grid_size) - (speed * TIME) + cell_offset;
    vec2 cell_num = floor(grid_uv); // cell indices
    vec2 local_pos = fract(grid_uv); // position inside the cell	
	
	// get draw size for this cell
	vec2 random_offset = random_seed + cell_num;
#if USE_ROTATION	
	float draw_size = mix(draw_size_min, min(draw_size_max, INV_SQRT2), random(random_offset)); 
	float edge_margin = draw_size * INV_SQRT2;		
	float tile_rot_speed = 
		rot_global_speed * 
		(step(0.5, random(cell_num + 1.0)) * 2.0 - 1.0) * // -1 or 1 (rotation direction)
		mix(rot_min_speed, rot_max_speed, random(cell_num + 2.0)); // rotation speed
#else
	float draw_size = mix(draw_size_min, draw_size_max, random(random_offset)); 
	float edge_margin = draw_size * 0.5;
	float tile_rot_speed = 0.0;
#endif
	
	// get "random" center for this cell
	vec2 draw_center = vec2(
	    mix(edge_margin, 1.0 - edge_margin, random(cell_num + 3.0)),
	    mix(edge_margin, 1.0 - edge_margin, random(cell_num + 4.0))
	);		
	
	// get random color
	vec4 tile_color = vec4(1.0);
#if USE_COLOR_MODULATION
	tile_color.rgb = mix(color_a.rgb, color_b.rgb, random(cell_num + 5.0));
	tile_color.a = mix(color_a.a, color_b.a, random(cell_num + 6.0));
#endif	
	
	return draw_tile(default_color, local_pos, draw_center, draw_size, tile_rot_speed, tile_color);
}

void fragment() {	
	vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
	color = draw_layer(
		color, 
		g_random_seed, 
		UV, 
		g_grid_size, 
		g_speed, 
		g_cell_offset, 
		g_draw_size_min, 
		g_draw_size_max	
#if USE_ROTATION		
		,g_rot_global_speed
		,g_rot_min_speed
		,g_rot_max_speed
#endif
#if USE_COLOR_MODULATION
		,g_color_a
		,g_color_b
#endif
	);
		
	// draw tile
	COLOR = color;
}
Live Preview
Tags
splatter, tiler
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from ProfesorShader

Related shaders

guest

0 Comments
Oldest
Newest Most Voted