this patch adds a number of stereo viewing modes (shutter glasses and video glasses...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 5 Aug 2004 13:50:38 +0000 (13:50 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 5 Aug 2004 13:50:38 +0000 (13:50 +0000)
added r_stereo_redblue and r_stereo_redgreen and r_stereo_redcyan (anaglyph 3d glasses)
added r_stereo_sidebyside (no glasses, recommend using the smallest viewsize to get them lined up with your eyes, then stare straight ahead...  warning: eye strain)
added r_stereo_separation (sets how far apart the eyes are in the world, default is 4 units, technically this should be 1.33, about 2 inches, but the quake player is a midget compared to the world...  so that doesn't look right)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4299 d7cf8633-e32d-0410-b094-e92efae38249

client.h
gl_backend.c
gl_rmain.c
gl_rsurf.c
r_shadow.c

index 469ed9b..8e040c9 100644 (file)
--- a/client.h
+++ b/client.h
@@ -754,6 +754,9 @@ typedef struct
        // view transform
        matrix4x4_t viewentitymatrix;
 
        // view transform
        matrix4x4_t viewentitymatrix;
 
+       // which color components to allow (for anaglyph glasses)
+       int colormask[4];
+
        // fullscreen color blend
        float viewblend[4];
 
        // fullscreen color blend
        float viewblend[4];
 
index a06484b..4632395 100644 (file)
@@ -9,6 +9,11 @@ cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0"};
 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0"};
 cvar_t gl_paranoid = {0, "gl_paranoid", "0"};
 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0"};
 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0"};
 cvar_t gl_paranoid = {0, "gl_paranoid", "0"};
 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0"};
+cvar_t r_stereo_separation = {0, "r_stereo_separation", "4"};
+cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0"};
+cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0"};
+cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0"};
+cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0"};
 
 cvar_t r_render = {0, "r_render", "1"};
 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1"};
 
 cvar_t r_render = {0, "r_render", "1"};
 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1"};
@@ -206,6 +211,11 @@ void gl_backend_init(void)
 
        Cvar_RegisterVariable(&r_render);
        Cvar_RegisterVariable(&r_waterwarp);
 
        Cvar_RegisterVariable(&r_render);
        Cvar_RegisterVariable(&r_waterwarp);
+       Cvar_RegisterVariable(&r_stereo_separation);
+       Cvar_RegisterVariable(&r_stereo_sidebyside);
+       Cvar_RegisterVariable(&r_stereo_redblue);
+       Cvar_RegisterVariable(&r_stereo_redcyan);
+       Cvar_RegisterVariable(&r_stereo_redgreen);
        Cvar_RegisterVariable(&gl_polyblend);
        Cvar_RegisterVariable(&gl_dither);
        Cvar_RegisterVariable(&gl_lockarrays);
        Cvar_RegisterVariable(&gl_polyblend);
        Cvar_RegisterVariable(&gl_dither);
        Cvar_RegisterVariable(&gl_lockarrays);
@@ -1287,13 +1297,13 @@ showtris:
                        Cvar_Set ("viewsize","30");
                if (scr_viewsize.value > 120)
                        Cvar_Set ("viewsize","120");
                        Cvar_Set ("viewsize","30");
                if (scr_viewsize.value > 120)
                        Cvar_Set ("viewsize","120");
-               
+
                // bound field of view
                if (scr_fov.value < 1)
                        Cvar_Set ("fov","1");
                if (scr_fov.value > 170)
                        Cvar_Set ("fov","170");
                // bound field of view
                if (scr_fov.value < 1)
                        Cvar_Set ("fov","1");
                if (scr_fov.value > 170)
                        Cvar_Set ("fov","170");
-       
+
                // intermission is always full screen
                if (cl.intermission)
                {
                // intermission is always full screen
                if (cl.intermission)
                {
@@ -1311,12 +1321,12 @@ showtris:
                        size = scr_viewsize.value * (1.0 / 100.0);
                        size = min(size, 1);
                }
                        size = scr_viewsize.value * (1.0 / 100.0);
                        size = min(size, 1);
                }
-       
+
                r_refdef.width = vid.realwidth * size;
                r_refdef.height = vid.realheight * size;
                r_refdef.x = (vid.realwidth - r_refdef.width)/2;
                r_refdef.y = (vid.realheight - r_refdef.height)/2;
                r_refdef.width = vid.realwidth * size;
                r_refdef.height = vid.realheight * size;
                r_refdef.x = (vid.realwidth - r_refdef.width)/2;
                r_refdef.y = (vid.realheight - r_refdef.height)/2;
-       
+
                // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
                r_refdef.fov_x = scr_fov.value * cl.viewzoom;
                r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
                // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
                r_refdef.fov_x = scr_fov.value * cl.viewzoom;
                r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
@@ -1335,23 +1345,85 @@ showtris:
                        }
                }
 
                        }
                }
 
-               R_RenderView();
+               r_refdef.colormask[0] = 1;
+               r_refdef.colormask[1] = 1;
+               r_refdef.colormask[2] = 1;
+
+               if (r_stereo_redblue.integer || r_stereo_redcyan.integer || r_stereo_redgreen.integer)
+               {
+                       matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
+                       r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][0];
+                       r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
+                       r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][2];
+
+                       r_refdef.colormask[0] = 1;
+                       r_refdef.colormask[1] = 0;
+                       r_refdef.colormask[2] = 0;
 
 
-               if (scr_zoomwindow.integer)
+                       R_RenderView();
+
+                       r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][0];
+                       r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
+                       r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][2];
+
+                       r_refdef.colormask[0] = 0;
+                       r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
+                       r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
+
+                       R_RenderView();
+
+                       r_refdef.viewentitymatrix = originalmatrix;
+               }
+               else if (r_stereo_sidebyside.integer)
                {
                {
-                       float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
-                       float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
-                       r_refdef.width = vid.realwidth * sizex;
-                       r_refdef.height = vid.realheight * sizey;
-                       r_refdef.x = (vid.realwidth - r_refdef.width)/2;
-                       r_refdef.y = 0;
-                       r_refdef.fov_x = scr_zoomwindow_fov.value;
-                       r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height);
+                       matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
+                       r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][0];
+                       r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
+                       r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][2];
 
 
+                       r_refdef.width = vid.realwidth * size / 2.5;
+                       r_refdef.height = vid.realheight * size / 2.5;
+                       r_refdef.x = (vid.realwidth - r_refdef.width * 2.5) * 0.5;
+                       r_refdef.y = (vid.realheight - r_refdef.height)/2;
+
+                       R_RenderView();
+
+                       r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][0];
+                       r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
+                       r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][2];
+
+                       r_refdef.x = (vid.realwidth - r_refdef.width * 2.5) * 0.5 + r_refdef.width * 1.5;
+               
                        R_RenderView();
                        R_RenderView();
+
+                       r_refdef.viewentitymatrix = originalmatrix;
                }
                }
+               else
+               {
+                       R_RenderView();
+
+                       if (scr_zoomwindow.integer)
+                       {
+                               float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
+                               float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
+                               r_refdef.width = vid.realwidth * sizex;
+                               r_refdef.height = vid.realheight * sizey;
+                               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+                               r_refdef.y = 0;
+                               r_refdef.fov_x = scr_zoomwindow_fov.value;
+                               r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+                               R_RenderView();
+                       }
+               }
+
+               r_refdef.colormask[0] = 1;
+               r_refdef.colormask[1] = 1;
+               r_refdef.colormask[2] = 1;
        }
 
        }
 
+       GL_ColorMask(1,1,1,1);
+
        // draw 2D stuff
        R_DrawQueue();
 
        // draw 2D stuff
        R_DrawQueue();
 
index 53f4243..36a3905 100644 (file)
@@ -626,11 +626,13 @@ void R_RenderView(void)
        r_view_fov_x = bound(1, r_refdef.fov_x, 170);
        r_view_fov_y = bound(1, r_refdef.fov_y, 170);
        r_view_matrix = r_refdef.viewentitymatrix;
        r_view_fov_x = bound(1, r_refdef.fov_x, 170);
        r_view_fov_y = bound(1, r_refdef.fov_y, 170);
        r_view_matrix = r_refdef.viewentitymatrix;
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
 
        // GL is weird because it's bottom to top, r_view_y is top to bottom
        qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        GL_ScissorTest(true);
 
        // GL is weird because it's bottom to top, r_view_y is top to bottom
        qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        GL_ScissorTest(true);
+       GL_DepthMask(true);
        R_ClearScreen();
        R_TimeReport("setup");
 
        R_ClearScreen();
        R_TimeReport("setup");
 
index 2f41c86..8ad9f9f 100644 (file)
@@ -764,7 +764,7 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture
                        GL_LockArrays(0, 0);
                }
        }
                        GL_LockArrays(0, 0);
                }
        }
-       GL_ColorMask(1,1,1,1);
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
 }
 
 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
 }
 
 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
@@ -1967,7 +1967,7 @@ void R_Q3BSP_DrawSkyFace(entity_render_t *ent, q3msurface_t *face)
        GL_LockArrays(0, face->num_vertices);
        R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
        GL_LockArrays(0, 0);
        GL_LockArrays(0, face->num_vertices);
        R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
        GL_LockArrays(0, 0);
-       GL_ColorMask(1,1,1,1);
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
 }
 
 void R_Q3BSP_DrawFace_OpaqueWall_Pass_OpaqueGlow(entity_render_t *ent, q3msurface_t *face)
 }
 
 void R_Q3BSP_DrawFace_OpaqueWall_Pass_OpaqueGlow(entity_render_t *ent, q3msurface_t *face)
index e6996fc..4fc6534 100644 (file)
@@ -919,7 +919,7 @@ void R_Shadow_Stage_LightWithoutShadows(void)
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
-       GL_ColorMask(1, 1, 1, 1);
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        qglDepthFunc(GL_EQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_CULL_FACE);
        qglDepthFunc(GL_EQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_CULL_FACE);
@@ -944,7 +944,7 @@ void R_Shadow_Stage_LightWithShadows(void)
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
-       GL_ColorMask(1, 1, 1, 1);
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        qglDepthFunc(GL_EQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_STENCIL_TEST);
        qglDepthFunc(GL_EQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_STENCIL_TEST);
@@ -970,7 +970,7 @@ void R_Shadow_Stage_End(void)
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
        qglPolygonOffset(0, 0);
        //qglDisable(GL_POLYGON_OFFSET_FILL);
        GL_Color(1, 1, 1, 1);
-       GL_ColorMask(1, 1, 1, 1);
+       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        qglDepthFunc(GL_LEQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
        qglDepthFunc(GL_LEQUAL);
        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
@@ -1579,7 +1579,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        }
                        // this final code is shared
                        R_Mesh_State(&m);
                        }
                        // this final code is shared
                        R_Mesh_State(&m);
-                       GL_ColorMask(1,1,1,0);
+                       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
@@ -1809,7 +1809,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                                }
                        }
                        R_Mesh_State(&m);
                                }
                        }
                        R_Mesh_State(&m);
-                       GL_ColorMask(1,1,1,0);
+                       GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
                        GL_LockArrays(0, numverts);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        VectorScale(lightcolor, colorscale, color2);
                        GL_LockArrays(0, numverts);