Slipgate texture warp

This is a shader I made in an attempt to recreate the slipgates from Quake. There is also an option to warp the screen UVs if you want to make something that looks a bit more like a portal.

Shader code
shader_type spatial;
render_mode unshaded, depth_draw_always; // NO LIGHTING!, "depth_draw_always" to 'fix' Z-ordering

uniform bool warp_ScreenSpace = false;
uniform sampler2D texture_albedo : source_color, filter_nearest;

void fragment() {
	vec2 uv = vec2(0.0);
	
	if(warp_ScreenSpace){
		uv = SCREEN_UV;
	}else{
		uv = UV;
	}
		
	// TODO: ADD NOISE SAMPLER INSTEAD OF USING TRIG?
	
	// TWEAK THE COEFFS AND/OR EQUATION FOR A DIFFERENT WARP PATTERN
	uv.x += sin(uv.y * 1.54 * PI + TIME) * cos(uv.y * 1.31 * PI + TIME) * 0.1; 
	uv.y += cos(uv.x * 1.74 * PI + TIME) * -sin(uv.y * 1.64 * PI + TIME) * 0.1; 

	vec4 color = texture(texture_albedo, uv * 2.0);

	ALBEDO = color.xyz;
	ALPHA = color.a;
}
Tags
quake, slime, slipgate, warp
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 Creatorbyte

Pixel Text Shader

Related shaders

Perspective Warp/Skew Shader

Cast Texture To Surface

Extrude 2D Texture in 3D

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Rob
Rob
9 days ago

Hello! This is a shader effect. The only issue I have with it is that it seems to only work when the mesh it’s applied to is at the word origin. I’m perhaps the least qualified for shaders so it is likely possible I just messed something up, but after attempts to make the portal center a global offset by rewriting the fragment method, I was still unable to make the effect work when the mesh is not at the world origin.

void fragment() {
    vec3 global_view = normalize((INV_VIEW_MATRIX * vec4(VIEW, 0)).xyz);
    vec3 global_vertex = (INV_VIEW_MATRIX * vec4(VERTEX, 1)).xyz;
    
    vec3 adjusted_portal_center = OBJECT_POSITION + PORTAL_CENTER;
    
    if (distance(global_vertex, adjusted_portal_center) > PORTAL_RADIUS) {
        ALPHA = 0.;
    } else {
        vec2 tube_uv = portal_uv(-global_view, global_vertex, adjusted_portal_center, PORTAL_NORMAL, PORTAL_SEAM, PORTAL_RADIUS);
        ALBEDO = texture(INSIDE_TEXTURE, tube_uv.xy).rgb;
        ALBEDO.b += tube_uv.y;
        ALPHA = 1.;
    }
}