This took me a few days to find some stuff. Click my video.
What Im trying to aim for is that the player walks on the street, then suddenly everything peels off into nightmare effect without having a scene.
I’ve tried the AnimationPlayer, doesn’t seem to switch the textures and not have a peeling effect.
This is what I found: Nightmare GLSL script, while surfing the internet.
I’ve attached it and AnimationPlayer to Meshinstance BoxShape
Even I tried to export GLB from Blender to Godot 4.5, its need Mesh Instance to get attach Nightmare Script… Sigh.
This is what I got GLSL script, its pretty useful.
shader_type spatial;
uniform sampler2D clean_tex;
uniform sampler2D nightmare_tex;
uniform sampler2D noise_tex;
uniform float transition : hint_range(0.0, 1.0) = 0.0;
// Vertex displacement parameters
uniform float peel_height = 0.5;
uniform float peel_frequency = 10.0;
void vertex() {
float mask = texture(noise_tex, UV).r;
float peel_factor = mask * transition;
}
void fragment() {
vec2 uv = UV;
float mask = texture(noise_tex, uv).r;
float t = smoothstep(transition - 0.1, transition + 0.1, mask);
vec3 clean = texture(clean_tex, uv).rgb;
vec3 nightmare = texture(nightmare_tex, uv).rgb;
ALBEDO = mix(clean, nightmare, t);
}
However, there is a problem when I played it. It won’t animate in-game.
I also attached another script to Node3D at all way top in the Scene.
WorldController. GLB
extends Node3D
@export var transition_speed := 0.3
@export var camera_shake_strength := 0.08
@export var camera_shake_speed := 20.0
@export var chunk_force := 10.0
var transitioning := false
var shake_time := 0.2
func start_otherworld():
# Play siren
$SirenSound.play()
# Show nightmare props
for obj in get_tree().get_nodes_in_group("nightmare_objects"):
obj.visible = true
# Replace walls with chunks
for wall in get_tree().get_nodes_in_group("world_walls"):
wall.visible = false
for chunk in get_tree().get_nodes_in_group("nightmare_chunks"):
chunk.visible = true
# Apply random impulse for “peeling off”
var direction = Vector3(
randf_range(-1,1),
randf_range(0.5,1.5),
randf_range(-1,1)
).normalized()
chunk.apply_impulse(Vector3.ZERO, direction * chunk_force)
transitioning = true
shake_time = 0.0
# Animate camera shake + fog
func _process(delta):
if transitioning:
# Camera shake
shake_time += delta
var player_cam = $Player
var shake_offset = Vector3(
sin(shake_time * camera_shake_speed),
cos(shake_time * camera_shake_speed * 1.2),
0
) * camera_shake_strength
player_cam.transform.origin = shake_offset
# Fog intensifies
var fog = $Fog.environment
fog.fog_density = lerp(0.05, 0.4, shake_time * 0.5)
# Optional: stop shake after 5s
if shake_time > 5:
transitioning = false
player_cam.transform.origin = Vector3.ZERO