From ed6a552a09b67a9499b772b7a60c4e425d7090a4 Mon Sep 17 00:00:00 2001 From: havoc Date: Thu, 5 Aug 2004 13:50:38 +0000 Subject: [PATCH 1/1] this patch adds a number of stereo viewing modes (shutter glasses and video glasses not supported yet) 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 | 3 ++ gl_backend.c | 100 +++++++++++++++++++++++++++++++++++++++++++-------- gl_rmain.c | 2 ++ gl_rsurf.c | 4 +-- r_shadow.c | 10 +++--- 5 files changed, 98 insertions(+), 21 deletions(-) diff --git a/client.h b/client.h index 469ed9b6..8e040c95 100644 --- a/client.h +++ b/client.h @@ -754,6 +754,9 @@ typedef struct // view transform matrix4x4_t viewentitymatrix; + // which color components to allow (for anaglyph glasses) + int colormask[4]; + // fullscreen color blend float viewblend[4]; diff --git a/gl_backend.c b/gl_backend.c index a06484bc..46323955 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -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 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"}; @@ -206,6 +211,11 @@ void gl_backend_init(void) 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); @@ -1287,13 +1297,13 @@ showtris: 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"); - + // 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); } - + 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); @@ -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_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(); diff --git a/gl_rmain.c b/gl_rmain.c index 53f42433..36a39051 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -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; + 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_DepthMask(true); R_ClearScreen(); R_TimeReport("setup"); diff --git a/gl_rsurf.c b/gl_rsurf.c index 2f41c867..8ad9f9ff 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -764,7 +764,7 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture 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) @@ -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_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) diff --git a/r_shadow.c b/r_shadow.c index e6996fc1..4fc65344 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -919,7 +919,7 @@ void R_Shadow_Stage_LightWithoutShadows(void) 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); @@ -944,7 +944,7 @@ void R_Shadow_Stage_LightWithShadows(void) 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); @@ -970,7 +970,7 @@ void R_Shadow_Stage_End(void) 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 @@ -1579,7 +1579,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements } // 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]--) @@ -1809,7 +1809,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements } } 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); -- 2.39.2