asymmetric viewing frustum stereo patch

Developer discussion of experimental fixes, changes, and improvements.

Moderators: Nexuiz Moderators, Moderators


  • Hi all,

    Please, check out this patch for stereo mode, the game is look just like Nvidia stereo driver.
    The patch was generated by diff on Ubuntu Hardy. Please, patch into version 2.4.2 engine source. Enjoy!!!

    The codes:

    diff -c -d
    *** MyDownloads/darkplaces/cl_screen.c 2008-04-10 03:03:36.000000000 -0400
    --- darkplaces/cl_screen.c 2008-07-01 08:25:30.000000000 -0400
    ***************
    *** 36,47 ****
    cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
    cvar_t cl_capturevideo_number = {CVAR_SAVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
    cvar_t r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
    - cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
    cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0", "side by side views for those who can't afford glasses but can afford eye strain (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
    cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
    cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
    cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
    cvar_t r_stereo_angle = {0, "r_stereo_angle", "0", "separation angle of eyes (makes the views look different directions, as an example, 90 gives a 90 degree separation where the views are 45 degrees left and 45 degrees right)"};
    cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
    cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
    cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
    --- 36,47 ----
    cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
    cvar_t cl_capturevideo_number = {CVAR_SAVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
    cvar_t r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
    cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0", "side by side views for those who can't afford glasses but can afford eye strain (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
    cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
    cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
    cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
    cvar_t r_stereo_angle = {0, "r_stereo_angle", "0", "separation angle of eyes (makes the views look different directions, as an example, 90 gives a 90 degree separation where the views are 45 degrees left and 45 degrees right)"};
    + cvar_t r_stereo_convergence = {CVAR_SAVE, "r_stereo_convergence", "4", "adjust to bring the game out of screen more or less, no negative number please.)"};
    cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
    cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
    cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
    ***************
    *** 806,812 ****
    Cvar_RegisterVariable (&cl_capturevideo_fps);
    Cvar_RegisterVariable (&cl_capturevideo_number);
    Cvar_RegisterVariable (&r_letterbox);
    ! Cvar_RegisterVariable(&r_stereo_separation);
    Cvar_RegisterVariable(&r_stereo_sidebyside);
    Cvar_RegisterVariable(&r_stereo_redblue);
    Cvar_RegisterVariable(&r_stereo_redcyan);
    --- 806,812 ----
    Cvar_RegisterVariable (&cl_capturevideo_fps);
    Cvar_RegisterVariable (&cl_capturevideo_number);
    Cvar_RegisterVariable (&r_letterbox);
    ! Cvar_RegisterVariable(&r_stereo_convergence);
    Cvar_RegisterVariable(&r_stereo_sidebyside);
    Cvar_RegisterVariable(&r_stereo_redblue);
    Cvar_RegisterVariable(&r_stereo_redcyan);
    ***************
    *** 1898,1904 ****
    void R_Shadow_EditLights_DrawSelectedLightProperties(void);

    int r_stereo_side;
    !
    void SCR_DrawScreen (void)
    {
    R_Mesh_Start();
    --- 1898,1904 ----
    void R_Shadow_EditLights_DrawSelectedLightProperties(void);

    int r_stereo_side;
    ! stereoframe_t stereo_frame;
    void SCR_DrawScreen (void)
    {
    R_Mesh_Start();
    ***************
    *** 2218,2234 ****
    {
    matrix4x4_t originalmatrix = r_refdef.view.matrix;
    matrix4x4_t offsetmatrix;
    ! Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * 0.5f, 0, 0, r_stereo_angle.value * 0.5f, 0, 1);
    Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);

    if (r_stereo_sidebyside.integer)
    r_stereo_side = 0;

    if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
    {
    ! r_refdef.view.colormask[0] = 1;
    ! r_refdef.view.colormask[1] = 0;
    ! r_refdef.view.colormask[2] = 0;
    }

    if (vid.stereobuffer)
    --- 2218,2236 ----
    {
    matrix4x4_t originalmatrix = r_refdef.view.matrix;
    matrix4x4_t offsetmatrix;
    ! Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_convergence.value * -0.5f, 0, 0, r_stereo_angle.value * 0.5f, 0, 1);
    Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);

    + stereo_frame = STEREO_RIGHT;
    +
    if (r_stereo_sidebyside.integer)
    r_stereo_side = 0;

    if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
    {
    ! r_refdef.view.colormask[0] = 0;
    ! r_refdef.view.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
    ! r_refdef.view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
    }

    if (vid.stereobuffer)
    ***************
    *** 2236,2252 ****

    SCR_DrawScreen();

    ! Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * -0.5f, 0, 0, r_stereo_angle.value * -0.5f, 0, 1);
    Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);

    if (r_stereo_sidebyside.integer)
    r_stereo_side = 1;

    if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
    {
    ! r_refdef.view.colormask[0] = 0;
    ! r_refdef.view.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
    ! r_refdef.view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
    }

    if (vid.stereobuffer)
    --- 2238,2256 ----

    SCR_DrawScreen();

    ! Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_convergence.value * 0.5f, 0, 0, r_stereo_angle.value * -0.5f, 0, 1);
    Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);

    + stereo_frame = STEREO_LEFT;
    +
    if (r_stereo_sidebyside.integer)
    r_stereo_side = 1;

    if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
    {
    ! r_refdef.view.colormask[0] = r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer;
    ! r_refdef.view.colormask[1] = 0;
    ! r_refdef.view.colormask[2] = 0;
    }

    if (vid.stereobuffer)
    *** MyDownloads/darkplaces/gl_backend.c 2008-05-07 03:25:00.000000000 -0400
    --- darkplaces/gl_backend.c 2008-07-01 08:07:45.000000000 -0400
    ***************
    *** 16,22 ****
    cvar_t gl_lockarrays = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"};
    cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
    cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
    !
    cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
    qboolean v_flipped_state = false;

    --- 16,22 ----
    cvar_t gl_lockarrays = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"};
    cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
    cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
    ! cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
    cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
    qboolean v_flipped_state = false;

    ***************
    *** 255,260 ****
    --- 255,261 ----
    Cvar_RegisterVariable(&gl_vbo);
    Cvar_RegisterVariable(&gl_paranoid);
    Cvar_RegisterVariable(&gl_printcheckerror);
    + Cvar_RegisterVariable(&r_stereo_separation);
    #ifdef NORENDER
    Cvar_SetValue("r_render", 0);
    #endif
    ***************
    *** 305,310 ****
    --- 306,327 ----
    R_Mesh_Matrix(&tempmatrix);
    }

    + void Setup_StereoView_Frustum (double *leftx, double *rightx, double frustumx, double znear)
    + {
    + double novfcl;

    + novfcl = znear / (110 / frustumx );

    + if(stereo_frame == STEREO_LEFT)

    + {

    + *leftx = -frustumx * znear + r_stereo_separation.value * novfcl ;

    + *rightx = frustumx * znear + r_stereo_separation.value * novfcl ;

    + }
    + if(stereo_frame == STEREO_RIGHT)
    + {

    + *leftx = -frustumx * znear - r_stereo_separation.value * novfcl ;

    + *rightx = frustumx * znear - r_stereo_separation.value * novfcl ;
    + }
    + }
    +
    static void GL_BuildFrustum(double m[16], double left, double right, double bottom, double top, double nearVal, double farVal)
    {
    m[0] = 2 * nearVal / (right - left);
    ***************
    *** 330,350 ****

    void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
    {
    ! double m[16];

    // set up viewpoint
    CHECKGLERROR
    qglMatrixMode(GL_PROJECTION);CHECKGLERROR
    // set view pyramid
    #if 1
    // avoid glGetDoublev whenever possible, it may stall the render pipeline
    // in the tested cases (nvidia) no measurable fps difference, but it sure
    // makes a difference over a network line with GLX
    ! GL_BuildFrustum(m, -frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);
    qglLoadMatrixd(m);CHECKGLERROR
    #else
    qglLoadIdentity();CHECKGLERROR
    ! qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
    qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
    #endif
    Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
    --- 347,388 ----

    void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
    {
    ! double m[16], left, right;

    // set up viewpoint
    CHECKGLERROR
    qglMatrixMode(GL_PROJECTION);CHECKGLERROR
    +
    // set view pyramid
    #if 1
    // avoid glGetDoublev whenever possible, it may stall the render pipeline
    // in the tested cases (nvidia) no measurable fps difference, but it sure
    // makes a difference over a network line with GLX
    !
    ! //assymetric viewing frustum for stereo mode
    !
    ! if (stereo_frame)

    ! {
    ! Setup_StereoView_Frustum (&left, &right, frustumx, zNear);

    ! GL_BuildFrustum(m, left, right, -frustumy * zNear, frustumy * zNear, zNear, zFar);
    ! }
    ! else
    ! {
    ! GL_BuildFrustum(m, -frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);
    ! }
    qglLoadMatrixd(m);CHECKGLERROR
    #else
    qglLoadIdentity();CHECKGLERROR
    !
    ! if (stereo_frame)

    ! {
    ! Setup_StereoView_Frustum (&left, &right, frustumx, zNear);

    ! qglFrustum(left, right, -frustumy * zNear, frustumy * zNear, zNear, zFar);
    ! }
    ! else
    ! {
    ! qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
    ! }
    qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
    #endif
    Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
    ***************
    *** 355,369 ****

    void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
    {
    ! double nudge, m[16];

    // set up viewpoint
    CHECKGLERROR
    qglMatrixMode(GL_PROJECTION);CHECKGLERROR
    qglLoadIdentity();CHECKGLERROR
    // set view pyramid
    nudge = 1.0 - 1.0 / (1<<23);
    ! m[ 0] = 1.0 / frustumx;
    m[ 1] = 0;
    m[ 2] = 0;
    m[ 3] = 0;
    --- 393,422 ----

    void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
    {
    ! double nudge, m[16], left, right;

    // set up viewpoint
    CHECKGLERROR
    qglMatrixMode(GL_PROJECTION);CHECKGLERROR
    qglLoadIdentity();CHECKGLERROR
    +
    + //assymetric viewing frustum for stereo mode
    +
    + if (stereo_frame)

    + {

    + Setup_StereoView_Frustum (&left, &right, frustumx, zNear);

    +
    + m[ 0] = 2 * zNear / (right - left);

    + m[ 8] = ( right + left ) / (right - left);

    + } else {

    +

    + m[ 0] = 1.0 / frustumx;

    + m[ 8] = 0;

    + }
    +
    // set view pyramid
    nudge = 1.0 - 1.0 / (1<<23);
    ! // m[ 0] = 1.0 / frustumx;
    m[ 1] = 0;
    m[ 2] = 0;
    m[ 3] = 0;
    ***************
    *** 371,377 ****
    m[ 5] = 1.0 / frustumy;
    m[ 6] = 0;
    m[ 7] = 0;
    ! m[ 8] = 0;
    m[ 9] = 0;
    m[10] = -nudge;
    m[11] = -1;
    --- 424,430 ----
    m[ 5] = 1.0 / frustumy;
    m[ 6] = 0;
    m[ 7] = 0;
    ! // m[ 8] = 0;
    m[ 9] = 0;
    m[10] = -nudge;
    m[11] = -1;
    *** MyDownloads/darkplaces/quakedef.h 2008-02-04 07:47:04.000000000 -0500
    --- darkplaces/quakedef.h 2008-06-30 11:03:34.000000000 -0400
    ***************
    *** 347,352 ****
    --- 347,362 ----

    void Sys_Shared_Init(void);

    + typedef enum stereoframe_s
    + {
    + STEREO_CENTER,
    + STEREO_RIGHT,
    + STEREO_LEFT,
    + }
    + stereoframe_t;
    +
    + extern stereoframe_t stereo_frame;
    +
    // Flag in size field of demos to indicate a client->server packet. Demo
    // playback will ignore this, but it may be useful to make DP sniff packets to
    // debug protocol exploits.
    Last edited by zuizme on Tue Jul 01, 2008 3:27 pm, edited 1 time in total.
    zuizme
    Newbie
     
    Posts: 5
    Joined: Sun Jun 29, 2008 3:45 pm

Tue Jul 01, 2008 2:07 pm

Tue Jul 01, 2008 2:25 pm

  • Can you explain WHAT you are doing different and why? Also, can you make a "diff -u" instead (more readable format for me) and post it for download, instead of pasting it into the forum (copypasting out of here breaks it)?

    Currently, the stereo separation works by moving the point of view a bit to the left or the right, but keeping the view direction. What did you change? How is it different from what can be achieved by the current cvars?

    Thanks
    1. Open Notepad
    2. Paste: ÿþMSMSMS
    3. Save
    4. Open the file in Notepad again

    You can vary the number of "MS", so you can clearly see it's MS which is causing it.
    User avatar
    divVerent
    Site admin and keyboard killer
     
    Posts: 3809
    Joined: Thu Mar 02, 2006 4:46 pm
    Location: BRLOGENSHFEGLE

Tue Jul 01, 2008 3:05 pm

  • divVerent wrote:Can you explain WHAT you are doing different and why? Also, can you make a "diff -u" instead (more readable format for me) and post it for download, instead of pasting it into the forum (copypasting out of here breaks it)?

    Currently, the stereo separation works by moving the point of view a bit to the left or the right, but keeping the view direction. What did you change? How is it different from what can be achieved by the current cvars?

    Thanks




    Well, I actually follow Paul Bourke method on the web, but the web page has been updated.
    The trick is in the calculation for a off-axis projection before changing the projection matrix and the calculation need the z projection value (some understand as the focal length).
    I've made the patch with diff -u, could you show me how to post the file for dowload. Thanks
    zuizme
    Newbie
     
    Posts: 5
    Joined: Sun Jun 29, 2008 3:45 pm

Tue Jul 01, 2008 8:52 pm

  • Hi all,

    Here is the link to download the stereo patch file.

    http://www.savefile.com/files/1644074

    There's only one new cvar "r_stereo_convergence" for player to adjust the out of screen effect to their own comfort. The r_stereo_separation cvar will increases the stereo depth effect. Do not use the r_stereo_angle, leave it at default 0. Enjoy.
    zuizme
    Newbie
     
    Posts: 5
    Joined: Sun Jun 29, 2008 3:45 pm

Sat Jul 19, 2008 11:29 am

  • This patch seems to do the following:
    1. render right then left rather than left then right.
    Why?
    2. renames the existing r_stereo_separation to r_stereo_convergence.
    Why?
    3. implements GL_PROJECTION matrix based stereo separation (using r_stereo_separation rather than r_stereo_convergence) and biases the frustum accordingly.
    Why?

    Could you explain what the purpose of this patch is?
    LordHavoc
    Site Admin
     
    Posts: 191
    Joined: Wed Mar 29, 2006 7:39 am
    Location: western Oregon, USA

Thu Aug 21, 2008 1:55 am

  • LordHavoc wrote:This patch seems to do the following:
    1. render right then left rather than left then right.
    Why?
    2. renames the existing r_stereo_separation to r_stereo_convergence.
    Why?
    3. implements GL_PROJECTION matrix based stereo separation (using r_stereo_separation rather than r_stereo_convergence) and biases the frustum accordingly.
    Why?

    Could you explain what the purpose of this patch is?



    Hi, sorry for the late reply. I haven't checked out the site for awhile.
    1. render right then left was just an order of rendering to the buffers, back_right then back_left. But it changeable.
    2. The stereo separation modify the projection matrix to create the asymmetric frustum, the stereo convergence modify the model view matrix it converge the two view at infinitive, that is why I've changed the name for the meaning of it. You can zero one of the two cvar to see the effect, if r_stereo_convergence=0 and r_stereo_separation=some_value then all things will be inside the monitor, if convergence have value and separation=0 then the stereo effect will be the original quake stereo effect, the toe-in method.
    3. Explained above, asymmetric frustum stereo must modify the projection matrix not just the model view matrix. The reason for two separate cvar was intended for player because everyone have their own comfort settings. But if you prefer you could use one cvar for both projection matrix and model view matrix.
    zuizme
    Newbie
     
    Posts: 5
    Joined: Sun Jun 29, 2008 3:45 pm

Fri Aug 22, 2008 1:52 am

  • zuizme wrote:3. Explained above, asymmetric frustum stereo must modify the projection matrix not just the model view matrix. The reason for two separate cvar was intended for player because everyone have their own comfort settings. But if you prefer you could use one cvar for both projection matrix and model view matrix.


    The r_stereo_separation cvar (and indeed, stereo rendering itself) did not exist in Quake, they are my additions, there is no reason to preserve the cvar.

    However I still do not understand why you are modifying the projection matrix.
    LordHavoc
    Site Admin
     
    Posts: 191
    Joined: Wed Mar 29, 2006 7:39 am
    Location: western Oregon, USA

Sat Aug 23, 2008 4:58 pm

  • LordHavoc wrote:
    zuizme wrote:3. Explained above, asymmetric frustum stereo must modify the projection matrix not just the model view matrix. The reason for two separate cvar was intended for player because everyone have their own comfort settings. But if you prefer you could use one cvar for both projection matrix and model view matrix.


    The r_stereo_separation cvar (and indeed, stereo rendering itself) did not exist in Quake, they are my additions, there is no reason to preserve the cvar.

    However I still do not understand why you are modifying the projection matrix.


    Well, I've actually been following this method by Paul Bourk
    http://local.wasp.uwa.edu.au/~pbourke/p ... reorender/

    This method calculate the asymmetric frustum then use the glFrustum to create the stereo projection matrix. In case of the matrix array the modification is the same as glFrustum.
    zuizme
    Newbie
     
    Posts: 5
    Joined: Sun Jun 29, 2008 3:45 pm



Return to Nexuiz - Development




Information
  • Who is online
  • Users browsing this forum: No registered users and 1 guest