(Blender Game Engine) How can I make scene/layer visible through a certain object without using python?
General idea of making a portal: you have a camera that sees what the portal should show. Then the output of the camera is rendered to the other portal as a texture.

Without python this is not possible though.



So here's a python way to do it (who would have thought? ;) ):

First we create the portal:

You can use whatever mesh you want but a plane mesh is probably the best. Name it something fitting, e.g. "portal". Make sure that when the object isn't rotated (=> rotation of 0,0,0) the object's normal(s) is/are facing towards the -Y-axis.



Next create a new image in the UV/image editor. Make sure that the aspect ratio of the image is the same as the one of your camera. E.g. if your resolution is 1920*1080 the image's resolution could also be 1920*1080.



Then select the portal, create a material and make it shadeless. Head over to the texture tab and create a texture. Assign the created image to it and unwrap the portal (U in edit mode). Set the texture's source to Generated and its mapping coordinates to UV. If the portal's dimensions aren't the same as the image's you should also move the UVs to the image's center.



Last thing left for the portal is the logic. Add an Always Sensor and a Python Controller. Activate the sensor's true level triggering. Now the controller: Choose Module instead of Script and type portal.main into the text field. Add a new text data block in the text editor and paste in the portal script from below. Name it portal.py. Then add two string game properties. Name one camera and the other one image. The value of the second one is the name of the image you created. We'll fill the other one later.



Now we take care of the camera. So just add one. Again, choose a name that makes sense like "portalCam". You can put this name in the camera property we created moments ago. 

Now the logic. Create a new script and paste the camera script in it. Name it something meaningful like portalCam.py. Add an Always Sensor and a Python Controller and activate true level triggering. Instead of choosing a module just choose the script that was just added. Create three string game properties, the first named camera, the second named portal and the third named reference. Put the name of your player's camera in the first property, the name of the portal in the second one.



The third property's value is the name of a reference object. It's the object the camera is referring to when calculating its position, so it's like another portal. The portal we created will look from the point of view of this reference object. You can use whatever you want, a plane (=> another portal) or just an empty would be fine. Add it and put its name in the reference property of the portal camera. All that is left to do is positioning and rotating it. The object's local Y-axis is the direction the camera will be looking in. To check the local transformation just hit &#9095; AltSpace and select local.



And now you're done! The portal shows the output of the camera which moves relative to the player camera's movement.



Here's an example .blend:





Scripts:

Portal Script:

from bge import logic, texture

scene = logic.getCurrentScene()


cont = logic.getCurrentController()
own = cont.owner
portalCam = scene.objects[own["camera"]]

matID = texture.materialID(own, "IM" + own["image"])
map_png = texture.Texture(own, matID)

source = texture.ImageRender(scene, portalCam)
source.background = (scene.world.backgroundColor[0]*255,scene.world.backgroundColor[1]*255,scene.world.backgroundColor[2]*255, 255)

map_png.source = source

def main():

    map_png.refresh(True)


Camera Script:

from bge import logic
from mathutils import Vector, Euler, Matrix
from math import pi

#getting all the objects
own = logic.getCurrentController().owner
scene = logic.getCurrentScene()
cam = scene.objects[own["camera"]]
portal = scene.objects[own["portal"]]
empty = scene.objects[own["reference"]]

#calculating the position of the portal camera
rotmat = empty.worldOrientation*portal.worldOrientation.inverted()*Matrix.Scale(-1, 3, portal.worldOrientation*Vector((1, 0, 0)))
diff = cam.worldPosition-portal.worldPosition
diff = rotmat*diff
own.worldPosition = empty.worldPosition+diff
own.worldOrientation = empty.worldOrientation
own.localOrientation = [own.localOrientation.to_euler()[0] + pi/2, own.localOrientation.to_euler()[1], own.localOrientation.to_euler()[2]]