Stereo Display Regions
A StereoDisplayRegion
is a special kind of DisplayRegion that contains
two views internally: one view for the left eye, and a different view for the
right eye. If you have a special 3-D display device, then Panda can use it to
deliver each view to the appropriate eye.
Alternatively, you can also simply create the two required views independently, one DisplayRegion for the left eye, and a separate DisplayRegion for the right eye. However, creating a single StereoDisplayRegion for both eyes at the same time is often more convenient.
When you call window.make_display_region()
, it will implicitly return a
StereoDisplayRegion instead of a regular DisplayRegion if your window or buffer
indicates that it supports stereo output (that is, if window.isStereo() returns
true). There are four ways that you can have a graphics output that supports
stereo output:
(1) You have a special 3-D display device and the drivers to support it, and
you put framebuffer-stereo 1
in your
Config.prc file. This tells Panda to activate the OpenGL interfaces to enable
the 3-D hardware.
(2) You put red-blue-stereo 1
in your
Config.prc file. This tells Panda to render the two different eyes in two
different colors, so that the traditional red-blue (or red-cyan) glasses, for
instance for 3-D comic books, can be used to view the scene in 3-D. Color is
distorted, so it is best if your scene relies on unsaturated color palettes.
Shades of gray work particularly well.
(3) You put side-by-side-stereo 1
in your
Config.prc file. This is similar to red-blue-stereo, above, but the two views
are rendered side-by-side in the same window. This is useful for developing
stereo applications, so you can see each view easily; it may also be useful
for environments such as head-mounted displays where the output spans two
different displays, and each display represents a different eye.
(4) As of Panda3D 1.9.0, you may create a stereo off-screen buffer without
special hardware support, assuming the card supports using multiple render
targets (most modern cards do), by setting the stereo flag in the
FrameBufferProperties
object. Panda3D will
automatically designate one of the draw buffers to contain the stereo view for
the other eye. When binding a texture to the color attachment for
render-to-texture, Panda3D will automatically initialize it as a
multiview texture containing both left and right
views. This is only supported in OpenGL as of writing.
Using a StereoDisplayRegion
A StereoDisplayRegion actually consists of two ordinary DisplayRegions,
created automatically. If you need to, you can access them individually with
sdr.get_left_eye()
or
sdr.get_right_eye()
.
Both the left and the right eye DisplayRegions actually share the same Camera
object. The thing that makes the view different for the left and the right eyes
is the stereo channel setting, which you can set via
dr.set_stereo_channel()
. (You can
change this setting on any DisplayRegion you like; it doesn’t have to be a
special StereoDisplayRegion. The only thing that a StereoDisplayRegion does is
it manages the internal left and right DisplayRegions automatically, but there’s
no reason you need to use a StereoDisplayRegion if you want to manage them
yourself.)
You can set a DisplayRegion’s stereo channel to one of Lens.SC_left
,
Lens.SC_right
, or Lens.SC_mono
. The default for a non-stereo
DisplayRegion is Lens.SC_mono
, which means the normal view from the center
of the camera. If you set it to either left or right, then the point of view is
slid automatically to the left or right, respectively, according to the stereo
lens parameters.
Setting the stereo channel to left or right also resets the texture view offset associated with the DisplayRegion: the default tex view offset is 0 for the left eye, and 1 for the right eye. This allows dual-view stereo textures to render properly in the DisplayRegion, so that the left view is visible in the left eye and the right view in the right eye. See Stereo/Multiview Textures for more about this feature.
The lens parameters can be controlled via
Lens.set_interocular_distance()
and
Lens.set_convergence_distance()
, or by the equivalent Config.prc
settings default-iod
and default-converge
. Refer to the following
illustration:
In this image, the camera indicated with “C” is the center view, the normal view
from the center of the camera view in the case of Lens.SC_mono
. “L” and “R”
represent the left and right points of view for the same camera, which will be
used in the case of Lens.SC_left
or Lens.SC_right
. The distance between
these two eyes, line “a” on the image, is the interocular distance, which should
be in the same units as the scene you are viewing.
The gray lines on the image represent the direction the camera appears to be facing into the scene. Both the left and the right eyes converge together at one point, which is the convergence distance. This distance is represented by line “b” on the image. Generally, the objects that are this distance away will appear to be in the screen plane. Objects that are closer than the convergence distance will appear to float in front of the screen, while objects that are further than the convergence distance will appear to be inside the screen.
Note that the default stereo frustums that Panda creates are off-axis frustums, not toe-in frustums. That is, both the left and the right eyes are still pointing in the precise same direction as the center camera, but the frustum is distorted a bit to make objects converge approximately at the requested distance. This is generally regarded as producing a superior stereo effect over the more naive toe-in approach, in which the left and right eyes are simply tilted towards each other to provide the required convergence.
If you require a different stereo frustum–for instance, if you wish to use toe-in stereo, or some other kind of stereo frustum of your choosing–you may simply set each DisplayRegion to use its own camera (instead of both sharing the same camera), and assign the particular frustum you wish to each eye.
Note
Prior to Panda3D 1.9.0, the convergence was being calculated incorrectly.
It has since been corrected. To restore the legacy behavior you can set the
stereo-lens-old-convergence
variable to true
.