FNAF Faked 3D Displacement Shader

I’ve seen several posts on the godot subreddit asking how to create the fake 3D effect from the Five Nights At Freddy’s series. I was a bit curious about how to do this and did a bit of digging. (Sources linked at bottom)

Simply, it works using a “Displacement Map”, which is basically a texture where each pixel is a greyscale value from 0.0 to 1.0 for how much to displace that pixel. I highly recommend using a CurveTexture which will let you manipulate the rate of distortion at the edges more easily.

The `scroll` uniform allows you to scroll to the left or right. Setting up a system in the code lets you “look” left and right in the fake 3D space.

This system seems to work with the source FNAF texture as well as some HDRIs downloaded from ambientcg. Feel free to remix if you feel like it could be improved! <3

If you happen to use this to make something cool, I’d love to see it! (@OfSquiggles on twitter)

 

Sources:

This Forum Post

This tutorial for GameMaker

Shader code
shader_type canvas_item;

// the left/right look amount. Ideally clamp this externally to prevent viewing edges
uniform float scroll = 0.0;

// keep positive to maintain pseudo3D effect.
uniform float displacement_scale = 2.0;

// easiest to just make this a curve texture, but making PNG gives a ton of control across the Y axis. Curve texture is just super smooth and doesn't have any issues with tearing.
uniform sampler2D displacement_map : hint_black;

void fragment(){
	vec2 uv = UV + vec2(scroll, 0.0); // scroll the UV
	float displacement = texture(displacement_map, UV).r; // pull amount from map
	displacement *= displacement_scale; // scale
	displacement *= (0.5 - uv.y); // transform based on distance from center horizontal
	COLOR = texture(TEXTURE, uv + vec2(0.0, displacement));// pull source image, displaced by scroll and vertical stretch.
}
Tags
fake3d, fnaf, warp
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 QueenOfSquiggles

QoS Style World Space Blue Noise Dither Effect

GDQuest BOTW Grass Shader Gradient Tweaks

Related shaders

Accurate FNAF “Panorama”

Jolly 1 office with displacement effect

displacement

Subscribe
Notify of
guest

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
b en
1 year ago

Nice shader, unfortunatly though I fear most people will not know how to use it as it doesnt work at all like the one in clickteam, and it is difficult to get looking completely accurate

Because of this I have uploaded a port of the original shader from the games. Just wanted to comment and let you know I wasnt just trying to be an asshole by uploading mine right after yours haha

The2AndOnly
The2AndOnly
1 year ago

It doesn’t work at all for me

The2AndOnly
The2AndOnly
1 year ago

I noticed these lines saying:

// easiest to just make this a curve texture, but making PNG gives a ton of control across the Y axis. Curve texture is just super smooth and doesn't have any issues with tearing.
uniform sampler2D displacement_map : hint_black;

Idk how to do that or what that means 🙁

CupHasCup
CupHasCup
11 months ago

Pretty Good!Nice Job!!!(In fact, I use a ColorRect that fills the full window to load this shader and this can make an effect like FNAF5)By the way, if you find that this shader doesn’t work in Godot4.0, try to change the “hint_black” to “hint_default_black”

CupHasCup
CupHasCup
11 months ago
Reply to  CupHasCup

Oh yeah, I changed some code to make the effect like FNAF5 like this:

shader_type canvas_item;

// the left/right look amount. Ideally clamp this externally to prevent viewing edges
uniform float scroll = 0.0;

// keep positive to maintain pseudo3D effect.
uniform float displacement_scale = 2.0;

uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;

// easiest to just make this a curve texture, but making PNG gives a ton of control across the Y axis. Curve texture is just super smooth and doesn't have any issues with tearing.
uniform sampler2D displacement_map : hint_default_black;

void fragment(){
	vec2 uv = SCREEN_UV + vec2(scroll, 0.0); // scroll the UV
	float displacement = texture(displacement_map, SCREEN_UV).r; // pull amount from map
	displacement *= displacement_scale; // scale
	displacement *= (0.5 - uv.y); // transform based on distance from center horizontal
	COLOR = texture(SCREEN_TEXTURE, uv + vec2(0.0, displacement));// pull source image, displaced by scroll and vertical stretch.
}

In fact, if you want to make an effect like FNAF5, don’t set the “scroll” parameter, set the ColorRect Object that loads this shader to be in the center of the screen, add a Sprite2D or other objects to load the image you want and let it follow the mouse, then you’ll get the effect

Mikey Hawt
Mikey Hawt
15 days ago

retard its called the perspective object