X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_backend.c;h=7dd9fefb21ac66d1efe9a48ed046bccfd7cd92c2;hb=d50445e9045ddea0d49857346597c57c129029e0;hp=f201d83920d453fc5edd5eb6ef4430b141f79fc8;hpb=2d3e69bcc8ddc5d1ed1a397c5a8944d44bcd44f4;p=xonotic%2Fdarkplaces.git diff --git a/gl_backend.c b/gl_backend.c index f201d839..7dd9fefb 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -7,11 +7,17 @@ cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"}; cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0"}; cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0"}; -cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "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 gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1"}; cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"}; @@ -143,7 +149,7 @@ static void R_Mesh_CacheArray_Shutdown(void); void GL_Backend_AllocArrays(void) { if (!gl_backend_mempool) - gl_backend_mempool = Mem_AllocPool("GL_Backend"); + gl_backend_mempool = Mem_AllocPool("GL_Backend", 0, NULL); R_Mesh_CacheArray_Startup(); } @@ -204,9 +210,15 @@ 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); - Cvar_RegisterVariable(&gl_delayfinish); Cvar_RegisterVariable(&gl_paranoid); Cvar_RegisterVariable(&gl_printcheckerror); #ifdef NORENDER @@ -692,7 +704,7 @@ void GL_TransformToScreen(const vec4_t in, vec4_t out) iw = 1.0f / out[3]; out[0] = r_view_x + (out[0] * iw + 1.0f) * r_view_width * 0.5f; out[1] = r_view_y + (out[1] * iw + 1.0f) * r_view_height * 0.5f; - out[2] = out[2] * iw; + out[2] = r_view_z + (out[2] * iw + 1.0f) * r_view_depth * 0.5f; } // called at beginning of frame @@ -1186,24 +1198,24 @@ void R_Mesh_Draw_ShowTris(int numverts, int numtriangles, const int *elements) ============================================================================== */ -qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg) +qboolean SCR_ScreenShot(char *filename, qbyte *buffer1, qbyte *buffer2, qbyte *buffer3, int x, int y, int width, int height, qboolean flipx, qboolean flipy, qboolean flipdiagonal, qboolean jpeg) { + int indices[3] = {0,1,2}; qboolean ret; - qbyte *buffer; if (!r_render.integer) return false; - buffer = Mem_Alloc(tempmempool, width*height*3); - qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); + qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1); CHECKGLERROR + Image_CopyMux (buffer2, buffer1, width, height, flipx, flipy, flipdiagonal, 3, 3, indices); + if (jpeg) - ret = JPEG_SaveImage_preflipped (filename, width, height, buffer); + ret = JPEG_SaveImage_preflipped (filename, width, height, buffer2); else - ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer); + ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer2, buffer3); - Mem_Free(buffer); return ret; } @@ -1245,7 +1257,92 @@ CalcFov float CalcFov (float fov_x, float width, float height) { // calculate vision size and alter by aspect, then convert back to angle - return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI; + return atan (((height/width)/vid_pixelaspect.value)*tan(fov_x/360.0*M_PI))*360.0/M_PI; +} + +int r_stereo_side; + +void SCR_DrawScreen (void) +{ + for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++) + { + R_Mesh_Start(); + + R_TimeReport("setup"); + + if (r_showtrispass) + { + rmeshstate_t m; + r_showtrispass = 0; + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthTest(GL_FALSE); + GL_DepthMask(GL_FALSE); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + GL_ShowTrisColor(0.2,0.2,0.2,1); + r_showtrispass = 1; + } + + if (scr_conlines < vid.conheight && cls.signon == SIGNONS) + { + float size; + + size = scr_viewsize.value * (1.0 / 100.0); + size = min(size, 1); + + if (r_stereo_sidebyside.integer) + { + r_refdef.width = vid.realwidth * size / 2.5; + r_refdef.height = vid.realheight * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100); + r_refdef.x = (vid.realwidth - r_refdef.width * 2.5) * 0.5; + r_refdef.y = (vid.realheight - r_refdef.height)/2; + if (r_stereo_side) + r_refdef.x += r_refdef.width * 1.5; + } + else + { + r_refdef.width = vid.realwidth * size; + r_refdef.height = vid.realheight * size * (1 - bound(0, r_letterbox.value, 100) / 100); + 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.fovscale_x; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y; + + 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.fovscale_x; + r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y; + + R_RenderView(); + } + } + + if (!r_stereo_sidebyside.integer) + { + r_refdef.width = vid.realwidth; + r_refdef.height = vid.realheight; + r_refdef.x = 0; + r_refdef.y = 0; + } + + // draw 2D stuff + R_DrawQueue(); + + R_Mesh_Finish(); + + R_TimeReport("meshfinish"); + } } /* @@ -1258,16 +1355,6 @@ text to the screen. */ void SCR_UpdateScreen (void) { - if (gl_delayfinish.integer) - { - R_Mesh_Finish(); - R_TimeReport("meshfinish"); - VID_Finish(); - R_TimeReport("finish"); - } - - R_Mesh_Start(); - if (r_textureunits.integer > gl_textureunits) Cvar_SetValueQuick(&r_textureunits, gl_textureunits); if (r_textureunits.integer < 1) @@ -1276,116 +1363,126 @@ void SCR_UpdateScreen (void) if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2)) Cvar_SetValueQuick(&gl_combine, 0); -showtris: - R_TimeReport("setup"); - - R_ClearScreen(); - - R_TimeReport("clear"); + // don't allow cheats in multiplayer + if (!cl.islocalgame && cl.worldmodel) + { + if (r_fullbright.integer != 0) + Cvar_Set ("r_fullbright", "0"); + if (r_ambient.value != 0) + Cvar_Set ("r_ambient", "0"); + } - if (scr_conlines < vid.conheight && cls.signon == SIGNONS) + // bound viewsize + if (scr_viewsize.value < 30) + 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) + sb_lines = 0; + else { - float size; - int contents; - - // bound viewsize - if (scr_viewsize.value < 30) - 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) - { - size = 1; - sb_lines = 0; - } + if (scr_viewsize.value >= 120) + sb_lines = 0; // no status bar at all + else if (scr_viewsize.value >= 110) + sb_lines = 24; // no inventory else + sb_lines = 24+16+8; + } + + r_refdef.fovscale_x = 1; + r_refdef.fovscale_y = 1; + if (r_waterwarp.value > 0 && cl.worldmodel) + { + Mod_CheckLoaded(cl.worldmodel); + if (CL_PointSuperContents(r_vieworigin) & SUPERCONTENTS_LIQUIDSMASK) { - if (scr_viewsize.value >= 120) - sb_lines = 0; // no status bar at all - else if (scr_viewsize.value >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - size = scr_viewsize.value * (1.0 / 100.0); - size = min(size, 1); + r_refdef.fovscale_x = 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); + r_refdef.fovscale_y = 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); } - - 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); - - if (cl.worldmodel) + } + + r_refdef.colormask[0] = 1; + r_refdef.colormask[1] = 1; + r_refdef.colormask[2] = 1; + + CHECKGLERROR + qglViewport(0, 0, vid.realwidth, vid.realheight); + qglDisable(GL_SCISSOR_TEST); + qglDepthMask(1); + qglColorMask(1,1,1,1); + qglClearColor(0,0,0,0); + qglClear(GL_COLOR_BUFFER_BIT); + CHECKGLERROR + + R_TimeReport("clear"); + + if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.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]; + + if (r_stereo_sidebyside.integer) + r_stereo_side = 0; + + if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer) { - Mod_CheckLoaded(cl.worldmodel); - contents = CL_PointSuperContents(r_vieworigin); - if (contents & SUPERCONTENTS_LIQUIDSMASK) - { - r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.015 + 0.985); - r_refdef.fov_y *= (sin(cl.time * 3.0) * 0.015 + 0.985); - } + r_refdef.colormask[0] = 1; + r_refdef.colormask[1] = 0; + r_refdef.colormask[2] = 0; } - R_RenderView(); + SCR_DrawScreen(); - 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_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_RenderView(); - } - } + if (r_stereo_sidebyside.integer) + r_stereo_side = 1; - // draw 2D stuff - R_DrawQueue(); + if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer) + { + 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; + } - if (r_showtrispass) - r_showtrispass = false; - else if (r_showtris.value > 0) - { - rmeshstate_t m; - GL_BlendFunc(GL_ONE, GL_ONE); - GL_DepthTest(GL_FALSE); - GL_DepthMask(GL_FALSE); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - r_showtrispass = true; - GL_ShowTrisColor(0.2,0.2,0.2,1); - goto showtris; - } + SCR_DrawScreen(); - if (gl_delayfinish.integer) - { - // tell driver to commit it's partially full geometry queue to the rendering queue - // (this doesn't wait for the commands themselves to complete) - qglFlush(); + r_refdef.viewentitymatrix = originalmatrix; } else { - R_Mesh_Finish(); - R_TimeReport("meshfinish"); - VID_Finish(); - R_TimeReport("finish"); + r_showtrispass = false; + SCR_DrawScreen(); + + if (r_showtris.value > 0) + { + rmeshstate_t m; + GL_BlendFunc(GL_ONE, GL_ONE); + GL_DepthTest(GL_FALSE); + GL_DepthMask(GL_FALSE); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + r_showtrispass = true; + GL_ShowTrisColor(0.2,0.2,0.2,1); + SCR_DrawScreen(); + r_showtrispass = false; + } } + + VID_Finish(); + R_TimeReport("finish"); } @@ -1393,12 +1490,16 @@ showtris: // dynamic vertex array buffer subsystem //=========================================================================== +// FIXME: someday this should be dynamically allocated and resized? float varray_vertex3f[65536*3]; +float varray_svector3f[65536*3]; +float varray_tvector3f[65536*3]; +float varray_normal3f[65536*3]; float varray_color4f[65536*4]; float varray_texcoord2f[4][65536*2]; float varray_texcoord3f[4][65536*3]; -float varray_normal3f[65536*3]; int earray_element3i[65536]; +float varray_vertex3f2[65536*3]; //=========================================================================== // vertex array caching subsystem