function ViewportWindow:RenderFrame(camCF, surfaceCF, surfaceSize,other)
local PI2 = math.pi/2
local Y_SPIN = CFrame.Angles(0, math.pi, 0)
local ZERO = Vector3.new(0, 0, 0)
local UNIT_Y = Vector3.new(0, 1, 0)
local UNIT_NZ = Vector3.new(0, 0, -1)
local XZ = Vector3.new(1, 0, 1)
local YZ = Vector3.new(0, 1, 1)
local camera = game.Workspace.CurrentCamera
camCF = camCF or camera.CFrame
local surfaceCF1, surfaceSize1 = self:GetSurfaceInfo(other)
if not (surfaceCF and surfaceSize) then
surfaceCF, surfaceSize = self:GetSurfaceInfo()
end
–local camOffset = surfaceCF:Inverse() * camera.CFrame
–
surfaceSize = SurfSizechec(surfaceSize)
surfaceSize1 = SurfSizechec(surfaceSize1)
local tc = surfaceCF * Vector3.new(0, surfaceSize.y/2, 0)
local bc = surfaceCF * Vector3.new(0, -surfaceSize.y/2, 0)
local cross = camCF.LookVector:Cross(surfaceCF.UpVector)
local right = cross:Dot(cross) > 0 and cross.Unit or camCF.RightVector
local levelCamCF = CFrame.fromMatrix(camCF.p, right, surfaceCF.UpVector, right:Cross(surfaceCF.UpVector))
local levelCamCFInv = levelCamCF:Inverse()
local csbc = levelCamCFInv * bc
local cstc = levelCamCFInv * tc
local v1 = (csbc*YZ).Unit
local v2 = (cstc*YZ).Unit
local alpha = math.sign(v1.y)*math.acos(v1:Dot(UNIT_NZ))
local beta = math.sign(v2.y)*math.acos(v2:Dot(UNIT_NZ))
local fh = 2*math.tan(math.rad(camera.FieldOfView)/2)
local hPrime = math.tan(beta) - math.tan(alpha)
local refHeight = hPrime / fh
--
local c2p = surfaceCF:VectorToObjectSpace(surfaceCF.p - camCF.p)
local c2pXZ = c2p * XZ
local c2pYZ = c2p * YZ
local dpX = c2pXZ.Unit:Dot(UNIT_NZ)
local camXZ = (surfaceCF:VectorToObjectSpace(camCF.LookVector) * XZ)
local scale = camXZ.Unit:Dot(c2pXZ.Unit) / UNIT_NZ:Dot(c2pXZ.Unit)
local tanArcCos = math.sqrt(1 - dpX*dpX) / dpX
--
local w, h = 1, (surfaceSize.x / surfaceSize.y)
local dx = math.sign(c2p.x*c2p.z)*tanArcCos
local dy = c2pYZ.y / c2pYZ.z * h
local d = math.abs(scale * refHeight * h)
local ncf = (surfaceCF - surfaceCF.p) * Y_SPIN * CFrame.new(0, 0, 0, w, 0, 0, 0, h, 0, dx, dy, d)
local c = {ncf:GetComponents()}
local max = c[1] - 1
for i = 1, #c do max = math.max(math.abs(c[i]), max) end
ncf = CFrame.new(c[1], c[2], c[3], c[4]/max, c[5]/max, c[6]/max, c[7]/max, c[8]/max, c[9]/max, c[10]/max, c[11]/max, c[12]/max)
--
-- can set w and h to 1 and use this as an alternative scaling method, but I find the above is better
local ratioXY = (surfaceSize.x / surfaceSize.y)
local ratioYX = (surfaceSize.y / surfaceSize.x)
if (ratioXY > ratioYX) then
self.SurfaceGUI.CanvasSize = Vector2.new(1024, 1024 * ratioYX)
else
self.SurfaceGUI.CanvasSize = Vector2.new(1024 * ratioXY, 1024)
end
local ncamCF = ncf + camCF.p
--
self.Camera.FieldOfView = camera.FieldOfView
self.Camera.CFrame = ncamCF
self.Camera.Focus = ncamCF * CFrame.new(0, 0, camCF:PointToObjectSpace(surfaceCF.p).z)
return ncamCF
end
this is from egomoose(edited by me), it helped me a lot when i was stuck on my portal effect.
don’t forget to make the SurfaceSize = SurfaceSize * Y_Spin