I’m trying to achieve something like a “window to a different dimension” using viewportframes. I have read every single article that I found about this, I even checked and tried EgoMoose’s portal effect and watched this video that explains how portals are created in games, but I’m still stuck.
What I have so far:
local cam = workspace.CurrentCamera;
local ui = script.Parent.Parent;
local fram = script.Parent:WaitForChild("Viewport");
local vCam = Instance.new("Camera");
vCam.CameraType = Enum.CameraType.Scriptable;
fram.CurrentCamera = vCam;
vCam.Parent = fram.Parent;
local screen = ui.Adornee;
local rs = game:GetService("RunService");
rs.RenderStepped:Connect(function(dt)
local dist = (cam.CFrame.Position - screen.Position).Magnitude;
if dist < 20 then
vCam.CFrame = cam.CFrame;
end
end
And there are no errors, but the whole camera view is stretched down to the part’s surface so obviously it doesn’t look like a portal. If I use a ScreenGui
instead of a SurfaceGui
, the parts appear where they should be and look perfect.
As the video explained too (4:07), all I would have to do is stretch up the ViewportFrame
to my screen’s size so it fits into the world around it, but I couldn’t find a way to achieve that. Maybe, if I could use a ScreenGui and mask it out so only the part’s surface is visible, it would work, but I have no idea how I could mask out a surface.
I also tried to take inspiration from EgoMoose but I barely understand anything of his code. I tried to just copy it, but nothing happened.
local rs = game:GetService("RunService");
rs.RenderStepped:Connect(function(dt)
local dist = (cam.CFrame.Position - ui.Adornee.Position).Magnitude;
if dist < 20 then
local camCF = cam.CFrame
local surfaceCF = screen.CFrame * CFrame.new(0, 0, -screen.Size.z/2)
local pDist = screen.Size.y/2 / math.tan(math.rad(vCam.FieldOfView)/2)
local rDist = (camCF.p - surfaceCF.p):Dot(surfaceCF.LookVector)
local adjust = rDist / pDist
local p = surfaceCF:PointToObjectSpace(camCF.p)
local s = p / screen.Size
fram.Position = UDim2.new(0.5 - s.x, 0, 0.5 - s.y, 0)
fram.Size = UDim2.new(4, 0, adjust, 0)
vCam.CFrame = CFrame.new(camCF.p) * (surfaceCF - surfaceCF.p) * CFrame.Angles(0, math.pi, 0)
end
end)
How could I achieve this window effect?
Note: The screen
is a cylinder, so the surface is round.
Thanks for any help!