Interior parallax system using viewportframe is glitching

I wanted to make a parallax 3d system for interior so that i don’t have to
individually place the furniture for every window

But its jittery and glitchy

Video

I took the @EgoMoose code for the camera cframing inside the viewportframe

i tried using parallel lua cuz i thought its because of performance but its still glitchy

da code:

local UP = Vector3.new(0, 1, 0)
local FOV120 = math.rad(120)
local PI2 = math.pi/2

for i,window in pairs(workspace.Windows:GetChildren()) do
	coroutine.wrap(function()
		-----///
		local sur = script.Parent.Parent.SurfaceGui:Clone()
		sur.Adornee = window
		sur.Parent = script.Parent.Parent
		
		

		local vpf = sur:WaitForChild("ViewportFrame")

		local camera = game.Workspace.CurrentCamera


		--

		local nCamera = Instance.new("Camera", vpf)
		nCamera.FieldOfView = 70
		vpf.CurrentCamera = nCamera

		--

	
		--

		local aspect = window.Size.x / window.Size.y
		vpf.Parent.CanvasSize = Vector2.new(camera.ViewportSize.y*aspect, camera.ViewportSize.y)
		vpf.LightDirection = -game.Lighting:GetSunDirection()
		vpf.BackgroundColor3 = window.Color
		local part = game.ReplicatedStorage.World.Model:Clone()
		part:SetPrimaryPartCFrame(window.CFrame)

		part:Clone().Parent = vpf
		
		local function GetSurfaceInfo(part)
			local partCF, partSize = part.CFrame, part.Size

			local back = -Vector3.FromNormalId(sur.Face)
			local axis = (math.abs(back.y) == 1) and Vector3.new(back.y, 0, 0) or UP
			local right = CFrame.fromAxisAngle(axis, PI2) * back
			local top = back:Cross(right).Unit

			local cf = partCF * CFrame.fromMatrix(-back*partSize/2, right, top, back)
			local size = Vector2.new((partSize * right).Magnitude, (partSize * top).Magnitude)

			return cf, size
		end
		
		game:GetService("RunService").RenderStepped:ConnectParallel(function(dt)
			
			task.desynchronize()
			local camCF = camera.CFrame
			local surfaceCF, surfaceSize = GetSurfaceInfo(window)
			local viewportSizeY = camera.ViewportSize.y

			local rPoint = surfaceCF:PointToObjectSpace(camCF.p)
			local sX, sY = rPoint.x / surfaceSize.x, rPoint.y / surfaceSize.y 

			local scaleX = 1 + math.abs(sX)*2
			local scaleY = 1 + math.abs(sY)*2
			local scale = math.sqrt(scaleX*scaleX + scaleY*scaleY)

			local rDist = (camCF.p - surfaceCF.p):Dot(surfaceCF.LookVector)
			local newFov = 2*math.atan2(surfaceSize.y/2, rDist)
			local clampedFov = math.clamp(math.deg(newFov), 1, 70)
			local pDist = surfaceSize.y/2 / math.tan(math.rad(clampedFov)/2)
			local adjust = rDist / pDist

			local factor = (newFov > FOV120 and adjust or 1) / scale
			local scaleCF = CFrame.new(0, 0, 0, factor, 0, 0, 0, factor, 0, 0, 0, 1)
			
			task.synchronize()

			vpf.Position = UDim2.new(vpf.AnchorPoint.x - sX, 0, vpf.AnchorPoint.y - sY, 0)
			vpf.Size = UDim2.new(scale, 0, scale, 0)
			vpf.BackgroundColor3 = sur.Adornee.Color

			sur.CanvasSize = Vector2.new(viewportSizeY*(surfaceSize.x/surfaceSize.y), viewportSizeY)
			nCamera.FieldOfView = clampedFov
			nCamera.CFrame = CFrame.new(camCF.p) * (surfaceCF - surfaceCF.p) * CFrame.Angles(0, math.pi, 0) * scaleCF

		end)
---///
	end)()
end

You said you don’t want to individually place furniture inside each window, but you could just have a script place them for you? You don’t need portal mechanics for something as simple as this…

that’s why i said I don’t want to place furniture inside them individually because I can’t do that to a brick with no indent, i want to do the portal mechanism so I could just slap the flat viewportframe on the brick to make it seem like there’s something inside them

is there even a point to using a viewport for parallax? why not just place the interior model there? using a viewport will replicate the effect of a parallax cube map but isnt it more expensive that just using the actuall model

edit: nvm disregard this i read the post further. my bad

-- this type of system exists in other games for performance reasons, using parallax CUBEMAPS and NOT render viewports. unfortunately roblox does not support this but when you use ViewportFrames to make an effect in roblox, it should be because you can’t achieve the effect by any other reasonable means. you can achieve furniture appearing inside a window by simply placing furniture inside the window. just do that.

-- what you’re trying to do will:
> tank the performance of your game, basically say goodbye to mobile players. every window will have to render all the contents within the room to its texture, defeating the whole purpose of parallax windows in the first place
> make the visual quality of your game far worse due to the limitations of viewports
> create even more scripting overhead as it now has to keep track of one camera per every window

-- this is not only a super lazy solution to not wanting to place down furniture yourself, but it will actively make your game worse. at this point if it matters that much to you just do what most games do and make windows fully opaque and reflective, or create a script that pastes models for you

-- if u still want to know the issue with your script is, this is not something that should be parallelized at all.
-- first of all you do not need to run task.desynchronize if your function is in a connectparallel
-- second of all a function that runs every frame should never be parallelized. you NEED this to run every frame for your effect to work, so you HAVE to block all rendering until this is completed. by parallelizing this you are telling the game that the game can continue processing as normal, so the game does just that.
-- thirdly, task.desynchronize will always halt the coroutine and resume it at a later time, i don’t know specifics but from the looks of it it looks like a frame, which is why your windows are lagging a frame or more behind

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.