I've been trying to figure out how to use viewports for displaying 3d stuff inside a gui ...

I have noticed that the content displayed in the vp doesn't look the same as in the camera preview (the camera underneath the vp). Let me show some images to illustrate the problem :

So : the scene has been setup symmetrically, the camera is only pointing down (no rotation around y-axis), vp & vpContainer have the same size, the vpc is not resizing the vp (stretch is false) ...
Result : the scene rendered in the vp is 'rotated' somehow. This is true both inside the editor & inside the game window.

Any idea what might be causing this ?

The camera preview is based on the aspect ratio of the app window (what you set in project settings) not the viewport size. If you click on the viewport container, it should show it as it will render. Something is off with your screenshot though. The viewport container should not be rotated. I just tried it, and it seems to work for me. So I don't know.

Well, the 3rd image is the view from the vpContainer ... I don't think you can rotate the vp or the vpContainer, so ... ???
Also, the camera preview should use the vp size, I think, since it will render there & not to the root vp ?

I'm currently in Godot 3.4.4. If your test was in the same version (thanks by the way !), could you perhaps send it to me so I can try to find what is different ? I really have no idea.

Thanks very much !

After opening your project, the difference is very obvious : your cube meshes are above the vp in the tree, mine are children of the vp. Aren't you just using the root viewport ? How would you use your setup in a game ?
Anyway, for my usecase (display 3d inside gui), I think I need to have the meshes as children of the vp ...

One good thing : your project opened in Godot 3.1 ... so I tried my setup in 3.1, and everything is fine. Must be a bug in 3.4.4 ?

It works the same with everything under the viewport. I don't think it's a bug. You probably just have some weird transform somewhere on one of your nodes.

Argh. Feeling so confused now.

Final question about viewports (I think I'll need to mention you in the credits of my game ; you have incredible patience !) : how do I resize a vp/vpc when the game window resizes ? I have tried wrapping it in a container node, but that doesn't seem to do anything ?
Maybe it's only possible through code ?

You have to check Stretch in the ViewportContainer and then the Viewport size doesn't matter (you can set it to something reasonable, but it will be overwritten). Then the size will be of the ViewportContainer, which you can set using the Control options or the Layout on the top of the window. For some reason it looks weird in the editor, but it works in game.

Not sure what I'm doing wrong (again =) ), but I can't get the resized window to look exactly like the original window as specified in the proj setts, if I'm just using the anchors etc.

I did get it to work with some code (and vpc stretch set to true) :

## ---
## resize vpc on game win resize
## ! req : vpc.stretch = true (vpc resizes vp)
## ? what to do with real FS (no win bar)
## ---
extends ViewportContainer

var orig_win_size:Vector2 = Vector2.ZERO
var orig_vpc_size:Vector2 = Vector2.ZERO
var orig_vpc_pos:Vector2 = Vector2.ZERO



func _ready():
	
	orig_win_size = get_tree().root.get_viewport().size
	orig_vpc_size = rect_size
	orig_vpc_pos = rect_position

	get_tree().root.connect("size_changed", self, "on_win_size_changed")


func on_win_size_changed():
	# ? does this also work for windowed -> fullscreen 
	
	print ("win size changed")
	
	# v1
	var new_win_size:Vector2 = get_viewport().size
	
	# v2 : same result
#	var new_win_size:Vector2 = OS.window_size

	# (1024, 600)	: small win (proj setts) : ok
	# (1536, 801) 	: ??? largest win should be 1920x1080 (or a little less for top border)
	# !!! fullscreen windowed takes into account 125% zoom in display settings of pc
	# if zoom = 100% : (1920, 1017) <-> (1024, 600)


	# change vpc size
	
	var win_ratio:Vector2 = Vector2(orig_win_size.x/new_win_size.x, orig_win_size.y/new_win_size.y)
	# (0.666667, 0.749064) 	 	: large win
	# (1, 1)					: orig small win
	
	var new_vpc_size:Vector2 = Vector2(orig_vpc_size.x/win_ratio.x, orig_vpc_size.y/win_ratio.y)
	print(orig_vpc_size, new_vpc_size)
	# (400, 300)(600, 400.5) 	: large win
	
	rect_size = new_vpc_size
	
	
	# change vpc loc
	
	var orig_top_mid:Vector2 = Vector2(orig_vpc_pos.x+orig_vpc_size.x/2, orig_vpc_pos.y)
	var new_top_mid:Vector2 = Vector2(orig_top_mid.x/win_ratio.x, orig_top_mid.y/win_ratio.y)
	var new_top_left:Vector2 = Vector2(new_top_mid.x-new_vpc_size.x/2, new_top_mid.y)
	
	rect_position = new_top_left