Need to use ViewportFrame to show other side of a part, like a window

I need to have the POV of the front of a part show on the back of the part through a SurfaceGui ViewportFrame. It should look as if you are seeing straight through the part.


My problem is that I can’t seem to get the camera in the right POV, position, or rotation.

This is my script, though it doesn’t exactly work correctly.

local player = game:GetService("Players").LocalPlayer

local Camera = workspace.CurrentCamera
local LastCFrame = Camera.CFrame

local playerGui = player:WaitForChild("PlayerGui")

local viewPart = workspace:WaitForChild("ViewPart")
--local viewPart2 = workspace:WaitForChild("ViewPart")

local surfaceGui:SurfaceGui = playerGui:WaitForChild("SurfaceGui")
surfaceGui.Adornee = viewPart
local viewportFrame:ViewportFrame = surfaceGui:WaitForChild("ViewportFrame")

local viewportCamera = Instance.new("Camera")
viewportFrame.CurrentCamera = viewportCamera
viewportCamera.Parent = viewportFrame

local function CameraMoved()
	if viewportFrame:FindFirstChildOfClass("Model") then
		viewportFrame:FindFirstChildOfClass("Model"):Destroy()
	end
	
	local viewportModel = Instance.new("Model")
	viewportModel.Parent = viewportFrame
	
	for _, child in pairs(workspace:GetChildren()) do
		if child:IsA("BasePart") or child:IsA("ParticleEmitter") or child:IsA("SpawnLocation") or child:IsA("Model") then
			if child:IsA("Terrain") then continue end
			local clone = child:Clone()
			if not clone then continue end
			clone.Parent = viewportModel
		end
	end
	
	--use the viewportCamera to show the other side of the viewpart, as if it's a hole in the part
	viewportCamera.CFrame = viewPart.CFrame * Camera.CFrame.Rotation + Vector3.new(viewPart.CFrame.X, Camera.CFrame.Y, viewPart.CFrame.Z)

	local horizontalDistance = (Vector3.new(Camera.CFrame.X, 0, Camera.CFrame.Z) - Vector3.new(viewportCamera.CFrame.X, 0, viewportCamera.CFrame.Z)).Magnitude
	local fov = 180 / (horizontalDistance+1)
	viewportCamera.FieldOfView = 70
end


game:GetService("RunService").RenderStepped:Connect(function()
	if (Camera.CFrame ~= LastCFrame) then
		CameraMoved()
	end
	LastCFrame = Camera.CFrame
end)

I know you’re not going for a portal, but this is a similar concept, and I couldn’t explain it better than Sebastian Lague even if I understood this concept in every single way. No one can explain anything better than him:

He explains the issue you’re having pretty well, starting at the very beginning of the video, 0:25-ish, but you should really watch the whole thing to help with this. Plus it’s a good video.

1 Like