How to make a mirror in Godot
HTML-код
- Опубликовано: 12 янв 2019
- scripts:
Camera: pastebin.com/Wew088KX
Mirror Cam: pastebin.com/Cf81Kt4u
Mirror Shader: pastebin.com/C7NZJj8p
looks like clipping planes might be added in 3.2, possibly even in-engine planar reflections: github.com/godotengine/godot/... - Игры
Keep in mind that having multiple cameras can be very slow. This is because it is continually rewriting the rendertotexture image multiple times per frame. It is much faster to use a reflective material, which ray-cast to see what gets reflected. This tends to be less accurate than using another camera but, is substantially faster to render. It also has the advantage of being able to reference reflection probes, which help make it more accurate.
For anyone struggling with the reflections misaligning and warping, try changing this line of code in the "mirror camera" gdscript:
$Viewport.size = Vector2(ProjectSettings.get_setting("display/window/size/width"), ProjectSettings.get_setting("display/window/size/height"))
into this:
$Viewport.size = Vector2(2000,1000)
I found that if you set the viewport with its width(2000) 2 times bigger than its height(1000) you get a constant proportion of reflected images regardless of display size(edit:as long as the display size has the same proportions (width=2*height)). Just remember to increase the viewport size if the reflection resolution isn't enough for you.
the vector2 uses the size of your game window when it runs. By default "ProjectSettings" set the display size to fill the whole screen (1028x720...or something).Sometimes the window size doesn't occupy the whole screen(like when you want to resize it or have a clingy menubar that refuses to leave your line of sight or something) so that affects your reflection, warping it. Best thing I found so far is to have a fixed viewport size.
Dude this tutorial is awesome. It was surprising that it is only 8k views especially on your channel
One solution to the object behind camera could be to add an area behind the mirror that hides any object it contacts with.
Interesting approach but it eats quite a bit performance. I believe Mario Sunshine used this technique, too. Therefore the mirrors had a quite low resolution, which broke the effect when the player camera got too close. You wouldn't want to overuse mirrors in games anyways.
Nevertheless, I think this might be a rather good solution for quick results. Thanks for the tutorial.
yeah, you could change the viewport resolution on the fly to make it lower resolution the farther away you are, might help
Thanks. I am super bad at shaders but I am sure this will help me make a portal effect for my game. Also thanks for the good tutorials they are some of the best
Thanks bro, I like people like you who are pretty awesome in programmation and design, who teaches others ! Tha,k you so much for the episode .
if i do this on my 3d first person game they will know a dark secret(the character is just a BEAN)
Lmao 😂
for those who can't make the viewporttexture because it's not local: in the shader under the resouces tab, you can set it to local :)
To anyone wondering how to cull the objects behind the camera, you can do it now in Godot 3.2.
You need to change the frustum of your camera.
You can get a look at this working example (not mine but helped me a lot) : twitter.com/JFonS_/status/1141266030758703104
I realize this is a two year old comment but how can you get this to work? I'm currently in godot 4.0
@@chalobeats8971 Did you ever manage? x)
Dude, thank you. I plan to start fooling around with some 3d stuff soon and no doubt this will be helpful.
I'm pretty sure you had to invert the basis x axis of the mirror camera because of an unnecessary invert of x value in the shader
got it to work but very performance heavy
thanks
How do I make two of these mirrors? If I try to make another object like that, it only captures picture from one side, and that side is valued by rotation of the first mirror in hierarchy. Any way to make it work properly?
So, I found solution by myself, I just needed to make unique material for each mirror in script, and instance the material with duplicate()
One way I think it would work would be to use a material that plane-clip on some uniform, but that is a hassle if you just want a default mirror surface. No viable method to do this unfortunately.
Hi Miziziziz, how do I mirror what a camera sees? I don't mean the main camera of a scene, just one for a viewport texture. All I need is for what the camera sees to be completely flipped horizontally without messing up alignment. For some reason I can't find how to do this anywhere on the forums or anything. Thanks
Pretty sure it's done in the mirror shader. The shader feeds "1.0 - SCREEN_UV.x" in the x UV coordinate, which effectively flips the image horizontally.
@@swifterik oh my god I didn't notice that. Thanks for finally being the person to answer lol
@@Hashbee no problem 😄
I might try to implement this mirror system myself. It looks fun. Have you managed to get your mirror working properly?
@@swifterik yeah the mirror works perfectly
Huge thanks for the tutorial, but using the same project in a VR Project makes a confused VR Picture.
Any idea for that?
Update this for Godot 4 please, the nodes work differently
this deserves to be on the godot shaders website
Hey for blocking objects between the virtual mirror and the mirror plane you can use oblique projection, see sebastians lauge's video on portals
I will use it to make portals.
really helpful tuto but the mirror image's aspect ratio gets messed up when you change the size of the viewport, i fixed this by setting the viewport of the mirror to the same size as the game viewport at runtime whenever the size changes rather than just grabbing the resolution from settings once.
heres the added code
# add to onready vars; get the mirror's viewport and the root node
@onready var viewport: SubViewport = $Viewport
@onready var root = $/root
# added line in _onready/_ready func
func _ready():
update_view_size()
root.size_changed.connect(update_view_size)
# function that updates viewport size
func update_view_size():
viewport.size = root.size
im guessing you could put in another suggestion i saw in the comments to increase perf by lowering the resolution of the mirror image by just making the mirror's subviewport a fraction of the root's dimensions, i.e. 0.5 * root.size but idk if that works.
also, if the fovs of the cameras are different, the mirrored image will look bigger or smaller than it should, i just fixed this by checking if the fov of the mirror cam is not the same as the main cam every frame and adjusting it if it is.