Re-Creating a Portal Effect,

To put it simply, this video goes over what Im trying to achieve. I understand how its done, but can’t seem to replicate the effect myself. Here’s the link.

I already am aware of how to store velocity and what not, I have a base portal animation, I just can’t seem to re-create it correctly, I’ve tried messing and researching on viewportframes but it dosent seem to be doing what Im trying to create, I can’t even go further into my game until I finish this part first. Thank you for your time.


I believe the easiest way of doing this would be with viewportframes


I’ve tried but it seems I simply can’t find out how to distort the viewportframes in such a way to produce this effect.


Using ViewportFrame is unreliable. Each time opening the portal requires the entire workspace to be cloned, which may cause part lag.


No you wouldn’t, you only need to clone the room that the portal is inside of, and then update the part’s position as the player moves around while looking at the portal


Yes, Viewportframes would be an approximate solution to this. Like others have said,

This is what you would need to do to create a portal of that sort.


while ViewportFrames are the most accurate solution, this is not their intended purpose and you should be wary of that when making anything for a production environment. Their primary purpose is to display small items inside there own render environment. ViewportFrames generate a texture, which also means constantly updating is not ideal for something like this.


If viewport frames aren’t working, try cloning another room with the portal as the point of reflection.
This does limit room size though.


Hey, that “ViewportFrame guy” here! I gave this a go, once upon a time.

This is actually almost impossible to do in Roblox. You’d have to rely on buggy behavior that we’ve been explicitly told not to do.

I haven’t watched the video, but I think I know what it’s going to say. At some step, At 4:10 in the video, it’ll discuss how you have to “crop” to a specific portion and make it fill up the frame. We don’t have the ability to do that. However, you could achieve that using Glass rendering bug and some resizing math. It won’t look great, but it works in theory. I don’t recommend it. Because it’ll look off, players will notice when they get close. They get close at crucial points in gameplay, so this isn’t yet viable on Roblox.

Edit: Perhaps one day ViewportFrames will be able to render other ViewportFrames inside themselves. If they do, you could use techniques similar to my image clipping module to crop and size the relevant image. Until then…


Not if you do it right!

I’ve made a few modules that make this very easy to implement. You would only clone things once!
My most recent handler module also lets you chose the FPS at which it would update object CFrames, so you could make the cubes move at only 30 FPS in the portal view. You could also make the map static, and therefore set the module to 0 FPS and massively save on performance since it’ll clone once and then never touch it.


I believe this is possible to do. As a matter of fact I took a good 30 mins to try and put this together.

It’s not perfect, but I believe I was able to convert the clipping problem to being axis aligned. I imagine with a bit of perspective “fudgery” I could make the clipping frame fit properly (which is why it’s not finished yet). That said the actual rotation aspect is clearly possible in the above video.


I’m very impressed. Didn’t think about that! Care to explain the technical details a bit more in depth?


Assuming I can solve this last hurdle I will do a write up.


You’re a gentleman and a scholar.


Okay, so I have something that’s worth talking about now.

I didn’t go through a nice solution that would make aspect and clipping work nicely. Instead out of laziness I choose to just use a “that’s a big number” solution. This is somewhat problematic because it’s still possible to get that cut off problem (although minimized).

Basically instead of doing the clipping and aspect I just use a large field of view and a stretched x size which doesn’t seem to effect the camera in viewport frames. Unfortunately it does result in some minor blurring. Again, I believe this could be fixed if I took the time :laughing:

I’m a little tired of working on this problem, but I know you yourself have a solid track record with viewport frames. I may come back to this problem in a few days, but until then I’ll upload the demo place so the community can have a run at it! :grin:

portal.rbxl (45.8 KB)


Edit: This isn’t a final solution for the reasons mentioned above, hence no write up yet.


EgoMoose to the rescue, though honestly it’d be so much nicer if non-Euclidean space were achievable in Roblox without hacking it together. I obviously have concerns about ViewportFrames but at the very least it does get that “other dimension” view down pat.


Getting back on topic before someone gets annoyed, let’s discuss this brilliant file you’ve shared.

The most pressing issue is pixelation and blur when close up. If you want players walking through, it needs to work up close too!
(The gif optimizations make this look awesome, but in game it’s just gross)

EgoMoose’s solution is the best we’ve got, and this is a side effect. So, how do we deal with this?

My solution? Game lore. Work with it. Call it “portal sickness”, a phenomenon that occurs when you get too close to a tear in the fabric of space. Add a bit of polish to it using some BlurEffects and particles, and bam: you have a workable product.

The next issue is the behavior at extreme angles. That’s a math issue that’s out of my area of expertise, unfortunately.

Overall, this is the best portal effect I’ve seen so far. As usual, EgoMoose blows everyone away.


There are some issues though.
I will however agree that this is really good.
@boatbomber has already told us the first problem.

But there is also this:

and this

The viewport frame seems to shorten itself at the bottom when you’re close and looking at 90 degrees. Now sure this isn’t exactly a terrible thing. But certainly noticeable.

@EgoMoose What exactly is the module drawClass for? Its not used in the main code and you can remove it without altering functionality. Is it for debugging?


I mentioned it, but because I lack any answers, I didn’t go in detail.


Yes, so quick answer. The drawClass is for debugging so it’s not really needed for functionality.

As for the pixelation problem and the extreme angles issue. It’s my understanding (of my own calculations) that this is because of a low crop aspect ratio.

I’ll explain in more detail the process that led to this calculation:

I figured the best way to start was to go with a case that I knew was 100% possible and then build up from there. This case was when the camera is axis aligned to the surface and only goes forward and backwards.

I figured this out by asking myself what would be the literal perfect position for my camera to be such that I didn’t even need to make an adjustment to the viewportframe? The answer to that is the cframe that causes the top and bottom of the surface to perfectly line up with my camera viewport.

This distance “perfect distance” is calculated as:

local pDist = window.Size.y/2 / math.tan(math.rad(nCamera.FieldOfView)/2)

As for why. It’s all about how cameras use the FOV angle.


Right. So I now knew the ideal distance, but how could I make this work for any distance? Well I could visually see that I just needed to adjust how I scaled the viewport frame to solve for non-perfect distance cases.

So I next calculated the “real distance” of the camera from the surface using the following:

local rDist = (camCF.p - surfaceCF.p):Dot(surfaceCF.LookVector)

I then found the ratio of the real over the perfect and used that to scale the viewport frame’s y size. This fully handles the case of depth.

The next, thing I asked was: How can I extend this such that I’m not yet rotating, but I am translating my camera? I.e. the rotation is still axis aligned but I can now go up and down and left and right.

Well the key here is to move translate the viewport frame, not the camera. So I converted the camera position to object space and found the scale values it would take to move from the center to the camera point projected on the surface.

local p = surfaceCF:PointToObjectSpace(camCF.p)
local s = p / window.Size

vpf.Position = - s.x, 0, 0.5 - s.y, 0)

That solves for that translation. The last thing is rotation. So far I’d been using the unmodified camera CFrame and that worked perfectly when it was axis-aligned, not so much when it isn’t. At first I was scratching my head, but then I realized something: how I rotate my camera shouldn’t effect what’s through the portal. With that eureka moment I realized I could just calculate and set a CFrame that was in the camera’s position, but axis aligned.

nCamera.CFrame = * (surfaceCF - surfaceCF.p) * CFrame.Angles(0, math.pi, 0)

I hope all that makes sense, because now I can talk about the problem, which is this line:

vpf.Size =, 0, adjust, 0)

You see when adjust < 1 it seems a number of problems arise. When at extreme angles both adjust < 1 and thus the viewport frame is really small and thus doesn’t fit the whole part (similar thing happens with the x-axis with far away frame translations).

Similarity when you’re really close to the surface the adjust value is also small and if you’re not at an extreme angle it may not see like it’s getting squished cause it matches the camera viewport height, but that’s what’s causing the blur.

So I think the solution is to as I mentioned above do some perspective fudgery to make further away parts seem closer (as mentioned in the video). This should allow us to use a higher aspect value.

Idk it’s def a tricky problem hence why I put it down for now.