How to create a portal effect or how to fake it

I want to make a portal but just visualize (static image inside portal) you can’t go inside of it like something this example

Any guide how to fake this I can only imagine of using transparent on top of portal but how to layer between portal , static image, behind environment (from example link you can see a mountain behind)

there - probably could be done simpler, I just wanned to practice my shader-fu

1 Like

Maybe is just WebGLRenderTarget with camera target rotation.

indeed, if you have second scene with .background set, and render it to the target, then the shader could be 2x simpler - here

portals can get complex, especially entering them. the easiest is most likely drei/portal. a first rough scaffold of the website you linked could be done in a few minutes.

if you want this in vanilla it can only be done with a shader. it’s not enough to render a scene into a webglrendertarget using the same camera and project it onto a plane, that would skew it when you turn the camera. the plane has to act as a mask into the virtual scene instead.

const PortalMaterialImpl = shaderMaterial(
  { map: null, resolution: new THREE.Vector2() },
  `varying vec2 vUv;
   void main() {
     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
     vUv = uv;
   }`,
  `uniform sampler2D map;
   uniform vec2 resolution;
   varying vec2 vUv;
   void main() {
     vec2 uv = gl_FragCoord.xy / resolution.xy;
     gl_FragColor = texture2D(map, uv);
     #include <tonemapping_fragment>
     #include <colorspace_fragment>
   }`
)

as for entering, drei/portal uses a propperty “blend”. if it’s > 0 it renders the main scene and the portal as a mix until it reaches 1 and then it only renders the portal fullscreen, without needing to project it.

Portal rendering is a big topic and the things we’re calling “portals” aren’t always the same as portals in the sense of portal rendering in engines like unreal etc. or the game “portal” which do additional mathematical trickery to determine portal → portal visibility… so that portals that aren’t on-screen don’t need to be rendered… nor portals not visible through other portals recursively etc.

You can use stencil buffer &| depth buffer &| alpha &| clipping planes, to composite different views/scenes without shaders… and/or you can use rendertargets and shaders. You can also use renderer.viewport to restrict drawing to a subset of the framebuffer.

You could draw your main scene… then clear the depth buffer to the near plane depth… render the portal shape using depthFunc: always, with polygonOffset to the far depth…, then render the second scene from the second camera. You could also set [clipping planes]
(three.js docs) to clip to a portal shape.

You could also use stencil to mask out a region.