Procedural Stained-Glass Shader

Procedural stained-glass shader

Shader code
/*
	プロシージャル ステンドグラス シェーダー by あるる(きのもと 結衣) @arlez80
	Procefural Stained Glass Shader by Yui Kinomoto @arlez80

	MIT License
*/
shader_type spatial;
// render_mode ;

uniform vec2 pixel_size = vec2( 0.001, 0.001 );
uniform float scale = 20.0;
uniform float shift = 0.05;
uniform float seed = 0.0;
uniform float alpha = 0.6;

vec3 hsv2rgb( float h, float s, float v )
{
	return (
		(
			clamp(
				abs( fract( h + vec3( 0.0, 2.0, 1.0 ) / 3.0 ) * 6.0 - 3.0 ) - 1.0
			,	0.0
			,	1.0
			) - 1.0
		) * s + 1.0
	) * v;
}

vec2 random( vec2 pos )
{ 
	return fract(
		sin(
			vec2(
				dot(pos, vec2(12.9898,78.233))
			,	dot(pos, vec2(-148.998,-65.233))
			)
		) * 43758.5453
	);
}

vec2 value_noise( vec2 pos )
{
	vec2 p = floor( pos );
	vec2 f = fract( pos );

	vec2 v00 = random( p + vec2( 0.0, 0.0 ) );
	vec2 v10 = random( p + vec2( 1.0, 0.0 ) );
	vec2 v01 = random( p + vec2( 0.0, 1.0 ) );
	vec2 v11 = random( p + vec2( 1.0, 1.0 ) );

	vec2 u = f * f * ( 3.0 - 2.0 * f );

	return mix( mix( v00, v10, u.x ), mix( v01, v11, u.x ), u.y );
}

vec2 glass( vec2 uv )
{
	vec2 v = uv * scale + vec2( seed, seed );
	vec2 v_floor = floor( v );
	vec2 v_fract = fract( v );

	vec2 min_p = vec2( 0.0, 0.0 );
	float min_dist = 2.0;

	for( int y = -1; y <= 1; y ++ ) {
		for( int x = -1; x <= 1; x ++ ) {
			vec2 n = vec2( float( x ), float( y ) );
			vec2 p = random( v_floor + n );
			float d = distance( v_fract, p + n );

			min_p = mix( min_p, p, float( d < min_dist ) );
			min_dist = min( min_dist, d );
		}
	}

	return min_p;
}

void fragment( )
{
	vec2 sobel[9];

	for( int y=0; y<3; y ++ ) {
		for( int x=0; x<3; x ++ ) {
			vec2 uv = UV + vec2( float( x-1 ), float( y-1 ) ) * pixel_size;
			sobel[y*3+x] = glass( uv );
		}
	}

	vec2 sobel_src_x = (
		sobel[0] * -1.0
	+	sobel[3] * -2.0
	+	sobel[6] * -1.0
	+	sobel[2] * 1.0
	+	sobel[5] * 2.0
	+	sobel[8] * 1.0
	);
	vec2 sobel_src_y = (
		sobel[0] * -1.0
	+	sobel[1] * -2.0
	+	sobel[2] * -1.0
	+	sobel[6] * 1.0
	+	sobel[7] * 2.0
	+	sobel[8] * 1.0
	);
	float sobel_result = length( sqrt( sobel_src_x * sobel_src_x + sobel_src_y * sobel_src_y ) );

	ALBEDO = hsv2rgb( sobel[4].x, 1.0, 1.0 ) * float( sobel_result == 0.0 );
	ALPHA = mix( 1.0, alpha, float( sobel_result == 0.0 ) );

	vec2 nv = (
		value_noise( UV * 300.0 ) * 0.25
	+	value_noise( UV * 500.0 ) * 0.25
	+	value_noise( UV * 1000.0 ) * 0.25
	+	value_noise( UV * 2100.0 ) * 0.25
	);
	NORMALMAP = normalize( vec3( nv.x, 1.0, nv.y ) );
}
Tags
glass, Procedural, Stained-glass
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 arlez80

Procedural Window Rain Drop Shader

Glitch Effect Shader for Godot Engine 4

Voronoi Synapse-ish Background Shader

Related shaders

Stochastic Procedural Texture Shader

Procedural Wang Tiling Shader

Procedural Electric Background Shader

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments