From 069527b0cff9d91784bba159329e01b0b94df752 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Fri, 1 Mar 2002 12:27:33 +0000 Subject: [PATCH] reenabled loading plaques (and cleaned up that code a lot) moved screenshot/envmap code from gl_backend.c to cl_screen.c (except for the GL SCR_ScreenShot function of course) cleaned up trailing whitespace in console.c backend between-batch overhead is now pretty much non-existent (set up state at start of frame, keep it until end of 3D rendering) default batch size is now 0 triangles (never batch) index array is not offset for first mesh in batch (which might be the only mesh in the batch) does not lock arrays until it tries to render the first mesh moved GL_LockArray/GL_UnlockArray from gl_models.c to gl_backend.c made GL calls in r_sky.c unnecessary (now uses R_Mesh_ClearDepth) made every enum in GL_PrintError (used by CHECKGLERROR) optional, for consistency (not that any GL headers would lack most of them) inlined MYgluPerspective removed a few unnecessary GL calls in frame setup code reformatted uses of CHECKGLERROR to be on the same line as the function they are checking (looks cleaner) increased MAX_TEXTUREUNITS from 4 to 8 (not that there is any code trying to use more than 2 textures anyway) calling R_RenderView with no worldmodel is no longer fatal (just returns) R_Mesh_Clear renamed to R_Mesh_Start R_Mesh_Finish added (ends 3D rendering) cleaned up some cruft in screen.h moved gldepthmin/max from vid_ files to gl_backend, and then commented it out anyway (not currently used) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1598 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_demo.c | 11 +- cl_parse.c | 2 +- cl_screen.c | 170 +++++++++-- console.c | 38 +-- gl_backend.c | 786 ++++++++++++++++++++++--------------------------- gl_backend.h | 36 ++- gl_models.c | 21 -- gl_rmain.c | 8 +- host.c | 2 +- host_cmd.c | 17 +- menu.c | 7 - r_sky.c | 28 +- screen.h | 19 +- vid_3dfxsvga.c | 2 - vid_glx.c | 2 - vid_wgl.c | 2 - 16 files changed, 589 insertions(+), 562 deletions(-) diff --git a/cl_demo.c b/cl_demo.c index 780b1f1c..40ada2d1 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -49,8 +49,6 @@ void CL_NextDemo (void) if (cls.demonum == -1) return; // don't play demos -// SCR_BeginLoadingPlaque (); - if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { cls.demonum = 0; @@ -291,7 +289,7 @@ void CL_Record_f (void) cls.forcetrack = track; Qprintf (cls.demofile, "%i\n", cls.forcetrack); - + cls.demorecording = true; } @@ -318,13 +316,11 @@ void CL_PlayDemo_f (void) return; } -// SCR_BeginLoadingPlaque(); - // // disconnect from server // CL_Disconnect (); - + // // open the demo file // @@ -340,6 +336,8 @@ void CL_PlayDemo_f (void) return; } + SCR_BeginLoadingPlaque (); + cls.demoplayback = true; cls.state = ca_connected; cls.forcetrack = 0; @@ -354,6 +352,7 @@ void CL_PlayDemo_f (void) cls.forcetrack = -cls.forcetrack; // ZOID, fscanf is evil // fscanf (cls.demofile, "%i\n", &cls.forcetrack); + } /* diff --git a/cl_parse.c b/cl_parse.c index 5a1b5b5f..ed530fdd 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -339,7 +339,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); break; case 4: -// SCR_EndLoadingPlaque (); // allow normal screen updates + SCR_EndLoadingPlaque (); // allow normal screen updates Con_ClearNotify(); break; } diff --git a/cl_screen.c b/cl_screen.c index a56acc4d..2278dc35 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -20,11 +20,19 @@ int clearconsole; int clearnotify; qboolean scr_disabled_for_loading; -//qboolean scr_drawloading; +qboolean scr_drawloading; //float scr_disabled_time; static qbyte menuplyr_pixels[4096]; +void DrawCrosshair(int num); +void V_CalcRefdef (void); +static void SCR_ScreenShot_f (void); +static void R_Envmap_f (void); + +// backend +void R_ClearScreen(void); + /* =============================================================================== @@ -215,7 +223,6 @@ void SCR_DrawPause (void) SCR_DrawLoading ============== */ -/* void SCR_DrawLoading (void) { cachepic_t *pic; @@ -226,7 +233,6 @@ void SCR_DrawLoading (void) pic = Draw_CachePic ("gfx/loading.lmp"); DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0); } -*/ @@ -295,9 +301,11 @@ SCR_BeginLoadingPlaque ================ */ -/* void SCR_BeginLoadingPlaque (void) { + if (scr_drawloading) + return; + S_StopAllSounds (true); // if (cls.state != ca_connected) @@ -311,12 +319,13 @@ void SCR_BeginLoadingPlaque (void) // scr_con_current = 0; scr_drawloading = true; - SCR_UpdateScreen (); + CL_UpdateScreen (); + CL_UpdateScreen (); + scr_drawloading = false; // scr_disabled_for_loading = true; // scr_disabled_time = realtime; } -*/ /* =============== @@ -324,14 +333,15 @@ SCR_EndLoadingPlaque ================ */ -/* void SCR_EndLoadingPlaque (void) { + if (!scr_drawloading) + return; + // scr_disabled_for_loading = false; scr_drawloading = false; Con_ClearNotify (); } -*/ //============================================================================= @@ -368,8 +378,6 @@ void SCR_DrawNotifyString (void) while (1); } -void DrawCrosshair(int num); - char r_speeds_string[1024]; int speedstringcount, r_timereport_active; double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0; @@ -518,6 +526,8 @@ void CL_Screen_Init(void) Cmd_AddCommand ("sizeup",SCR_SizeUp_f); Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("envmap", R_Envmap_f); scr_initialized = true; @@ -752,8 +762,108 @@ static void SCR_CalcRefdef (void) } } +/* +================== +SCR_ScreenShot_f +================== +*/ +void SCR_ScreenShot_f (void) +{ + int i; + char filename[16]; + char checkname[MAX_OSPATH]; +// +// find a file name to save it to +// + strcpy(filename, "dp0000.tga"); + + for (i=0 ; i<=9999 ; i++) + { + filename[2] = (i/1000)%10 + '0'; + filename[3] = (i/ 100)%10 + '0'; + filename[4] = (i/ 10)%10 + '0'; + filename[5] = (i/ 1)%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, filename); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==10000) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); + return; + } + + SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight); + Con_Printf ("Wrote %s\n", filename); +} + +/* +=============== +R_Envmap_f -void V_CalcRefdef (void); +Grab six views for environment mapping tests +=============== +*/ +struct +{ + float angles[3]; + char *name; +} +envmapinfo[6] = +{ + {{ 0, 0, 0}, "ft"}, + {{ 0, 90, 0}, "rt"}, + {{ 0, 180, 0}, "bk"}, + {{ 0, 270, 0}, "lf"}, + {{-90, 90, 0}, "up"}, + {{ 90, 90, 0}, "dn"} +}; + +static void R_Envmap_f (void) +{ + int j, size; + char filename[256], basename[256]; + + if (Cmd_Argc() != 3) + { + Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); + return; + } + + strcpy(basename, Cmd_Argv(1)); + size = atoi(Cmd_Argv(2)); + if (size != 128 && size != 256 && size != 512 && size != 1024) + { + Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); + return; + } + if (size > vid.realwidth || size > vid.realheight) + { + Con_Printf("envmap: your resolution is not big enough to render that size\n"); + return; + } + + envmap = true; + + r_refdef.x = 0; + r_refdef.y = 0; + r_refdef.width = size; + r_refdef.height = size; + + r_refdef.fov_x = 90; + r_refdef.fov_y = 90; + + for (j = 0;j < 6;j++) + { + sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name); + VectorCopy(envmapinfo[j].angles, r_refdef.viewangles); + R_ClearScreen(); + R_RenderView (); + SCR_ScreenShot(filename, vid.realx, vid.realy, size, size); + } + + envmap = false; +} //============================================================================= @@ -839,18 +949,10 @@ void SHOWLMP_clear(void) showlmp[i].isactive = false; } -void CL_UpdateScreen(void) +void CL_SetupScreenSize(void) { static float old2dresolution = -1; - if (scr_disabled_for_loading) - return; - - if (!scr_initialized || !con_initialized) - return; // not initialized yet - - R_TimeReport("other"); - VID_GetWindowSize (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight); VID_UpdateGamma(false); @@ -881,6 +983,17 @@ void CL_UpdateScreen(void) // determine size of refresh window SCR_CalcRefdef(); +} + +void CL_UpdateScreen(void) +{ + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + + R_TimeReport("other"); + + CL_SetupScreenSize(); DrawQ_Clear(); @@ -889,6 +1002,15 @@ void CL_UpdateScreen(void) R_TimeReport("setup"); + if (scr_drawloading) + { + scr_con_current = vid.conheight; + DrawQ_Clear(); + SCR_DrawLoading(); + SCR_UpdateScreen(); + return; + } + SCR_DrawRam(); SCR_DrawNet(); SCR_DrawTurtle(); @@ -901,6 +1023,14 @@ void CL_UpdateScreen(void) ui_draw(); + /* + if (scr_drawloading) + { + SCR_DrawLoading(); + if ( + } + */ + R_TimeReport("2d"); // add r_speeds text to queue diff --git a/console.c b/console.c index c5332a99..e6382e98 100644 --- a/console.c +++ b/console.c @@ -93,8 +93,8 @@ void Con_ToggleConsole_f (void) } else key_dest = key_console; - -// SCR_EndLoadingPlaque (); + + SCR_EndLoadingPlaque (); memset (con_times, 0, sizeof(con_times)); } @@ -109,7 +109,7 @@ void Con_Clear_f (void) memset (con_text, ' ', CON_TEXTSIZE); } - + /* ================ Con_ClearNotify @@ -118,12 +118,12 @@ Con_ClearNotify void Con_ClearNotify (void) { int i; - + for (i=0 ; i 1) ? "s: " : ":"); Con_DisplayList(list[0]); } - + if (v) { Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":"); Con_DisplayList(list[1]); } - + if (a) { Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":"); Con_DisplayList(list[2]); } } - + if (cmd) { strncpy(key_lines[edit_line] + 1, cmd, cmd_len); key_linepos = cmd_len + 1; diff --git a/gl_backend.c b/gl_backend.c index b0d287b0..562c447a 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -1,26 +1,84 @@ #include "quakedef.h" -cvar_t r_render = {0, "r_render", "1"}; -cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering +//cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"}; +cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "8192"}; +//cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"}; +cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "0"}; +cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "0"}; + +cvar_t r_render = {0, "r_render", "1"}; +cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering +cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"}; + +#ifdef DEBUGGL +int errornumber = 0; + +void GL_PrintError(int errornumber, char *filename, int linenumber) +{ + switch(errornumber) + { +#ifdef GL_INVALID_ENUM + case GL_INVALID_ENUM: + Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_INVALID_VALUE + case GL_INVALID_VALUE: + Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_INVALID_OPERATION + case GL_INVALID_OPERATION: + Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_STACK_OVERFLOW + case GL_STACK_OVERFLOW: + Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_STACK_UNDERFLOW + case GL_STACK_UNDERFLOW: + Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_OUT_OF_MEMORY + case GL_OUT_OF_MEMORY: + Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber); + break; +#endif +#ifdef GL_TABLE_TOO_LARGE + case GL_TABLE_TOO_LARGE: + Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber); + break; +#endif + default: + Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber); + break; + } +} +#endif + +float r_farclip, r_newfarclip; + +int polyindexarray[768]; + +static float viewdist; + +int c_meshs, c_meshtris, c_transmeshs, c_transtris; int lightscalebit; float lightscale; float overbrightscale; void SCR_ScreenShot_f (void); -static void R_Envmap_f (void); static int max_meshs; static int max_batch; static int max_verts; // always max_meshs * 3 #define TRANSDEPTHRES 4096 -//static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"}; -static cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "8192"}; -static cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"}; -static cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "0"}; - typedef struct buf_mesh_s { int depthmask; @@ -185,28 +243,22 @@ static void gl_backend_bufferchanges(int init) } } -float r_farclip, r_newfarclip; - static void gl_backend_newmap(void) { r_farclip = r_newfarclip = 2048.0f; } -int polyindexarray[768]; - void gl_backend_init(void) { int i; - Cvar_RegisterVariable (&r_render); - Cvar_RegisterVariable (&gl_dither); + Cvar_RegisterVariable(&r_render); + Cvar_RegisterVariable(&gl_dither); + Cvar_RegisterVariable(&gl_lockarrays); #ifdef NORENDER Cvar_SetValue("r_render", 0); #endif - Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddCommand ("envmap", R_Envmap_f); - Cvar_RegisterVariable(&gl_mesh_maxtriangles); Cvar_RegisterVariable(&gl_mesh_batchtriangles); Cvar_RegisterVariable(&gl_mesh_floatcolors); @@ -220,16 +272,29 @@ void gl_backend_init(void) } } -static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmax, ymax; +int arraylocked = false; - xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect; - ymax = zNear * tan( fovy * M_PI / 360.0 ); +void GL_LockArray(int first, int count) +{ + if (!arraylocked && gl_supportslockarrays && gl_lockarrays.integer) + { + qglLockArraysEXT(first, count); + CHECKGLERROR + arraylocked = true; + } +} - glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar ); +void GL_UnlockArray(void) +{ + if (arraylocked) + { + qglUnlockArraysEXT(); + CHECKGLERROR + arraylocked = false; + } } +//static float gldepthmin, gldepthmax; /* ============= @@ -238,39 +303,59 @@ GL_SetupFrame */ static void GL_SetupFrame (void) { + double xmax, ymax; + double fovx, fovy, zNear, zFar, aspect; + + // update farclip based on previous frame + r_farclip = r_newfarclip; + if (!r_render.integer) return; // glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen - gldepthmin = 0; - gldepthmax = 1; - glDepthFunc (GL_LEQUAL); - - glDepthRange (gldepthmin, gldepthmax); +// gldepthmin = 0; +// gldepthmax = 1; + glDepthFunc (GL_LEQUAL);CHECKGLERROR - // update farclip based on previous frame - r_farclip = r_newfarclip; +// glDepthRange (gldepthmin, gldepthmax);CHECKGLERROR // set up viewpoint - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); + glMatrixMode(GL_PROJECTION);CHECKGLERROR + glLoadIdentity ();CHECKGLERROR // y is weird beause OpenGL is bottom to top, we use top to bottom - glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height); -// yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI; - MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4.0 / 3.0, r_farclip); + glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);CHECKGLERROR + + // depth range + zNear = 1.0; + zFar = r_farclip; + + // fov angles + fovx = r_refdef.fov_x; + fovy = r_refdef.fov_y; + aspect = r_refdef.width / r_refdef.height; - glCullFace(GL_FRONT); + // pyramid slopes + xmax = zNear * tan(fovx * M_PI / 360.0) * aspect; + ymax = zNear * tan(fovy * M_PI / 360.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); + // set view pyramid + glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); +// glCullFace(GL_FRONT);CHECKGLERROR + + glMatrixMode(GL_MODELVIEW);CHECKGLERROR + glLoadIdentity ();CHECKGLERROR + + // put Z going up + glRotatef (-90, 1, 0, 0);CHECKGLERROR + glRotatef (90, 0, 0, 1);CHECKGLERROR + // camera rotation + glRotatef (-r_refdef.viewangles[2], 1, 0, 0);CHECKGLERROR + glRotatef (-r_refdef.viewangles[0], 0, 1, 0);CHECKGLERROR + glRotatef (-r_refdef.viewangles[1], 0, 0, 1);CHECKGLERROR + // camera location + glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);CHECKGLERROR // glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); @@ -278,25 +363,38 @@ static void GL_SetupFrame (void) // set drawing parms // // if (gl_cull.integer) - glEnable(GL_CULL_FACE); +// { +// glEnable(GL_CULL_FACE);CHECKGLERROR +// } // else -// glDisable(GL_CULL_FACE); +// { +// glDisable(GL_CULL_FACE);CHECKGLERROR +// } - glEnable(GL_BLEND); // was Disable - glEnable(GL_DEPTH_TEST); - glDepthMask(1); +// glEnable(GL_BLEND);CHECKGLERROR +// glEnable(GL_DEPTH_TEST);CHECKGLERROR +// glDepthMask(1);CHECKGLERROR } -static float viewdist; - -int c_meshs, c_meshtris, c_transmeshs, c_transtris; +static int mesh_blendfunc1; +static int mesh_blendfunc2; +static int mesh_blend; +static GLboolean mesh_depthmask; +static int mesh_depthtest; +static int mesh_unit; +static int mesh_clientunit; +static int mesh_texture[MAX_TEXTUREUNITS]; +static float mesh_texturergbscale[MAX_TEXTUREUNITS]; // called at beginning of frame -void R_Mesh_Clear(void) +void R_Mesh_Start(void) { + int i; if (!backendactive) Sys_Error("R_Mesh_Clear: called when backend is not active\n"); + CHECKGLERROR + gl_backend_bufferchanges(false); currentmesh = 0; @@ -315,64 +413,120 @@ void R_Mesh_Clear(void) c_transtris = 0; GL_SetupFrame(); -} -#ifdef DEBUGGL -void GL_PrintError(int errornumber, char *filename, int linenumber) -{ - switch(errornumber) + mesh_unit = 0; + mesh_clientunit = 0; + + for (i = 0;i < backendunits;i++) { - case GL_INVALID_ENUM: - Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber); - break; - case GL_INVALID_VALUE: - Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber); - break; - case GL_INVALID_OPERATION: - Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber); - break; - case GL_STACK_OVERFLOW: - Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber); - break; - case GL_STACK_UNDERFLOW: - Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber); - break; - case GL_OUT_OF_MEMORY: - Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber); - break; -#ifdef GL_TABLE_TOO_LARGE - case GL_TABLE_TOO_LARGE: - Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber); - break; -#endif - default: - Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber); - break; + mesh_texture[i] = 0; + mesh_texturergbscale[i] = 1; } -} -int errornumber = 0; -#endif + glEnable(GL_CULL_FACE);CHECKGLERROR + glCullFace(GL_FRONT);CHECKGLERROR + + mesh_depthtest = true; + glEnable(GL_DEPTH_TEST);CHECKGLERROR + + mesh_blendfunc1 = GL_ONE; + mesh_blendfunc2 = GL_ZERO; + glBlendFunc(mesh_blendfunc1, mesh_blendfunc2);CHECKGLERROR + + mesh_blend = 0; + glDisable(GL_BLEND);CHECKGLERROR + + mesh_depthmask = GL_TRUE; + glDepthMask(mesh_depthmask);CHECKGLERROR + + glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), &buf_vertex[0].v[0]);CHECKGLERROR + glEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR + if (gl_mesh_floatcolors.integer) + { + glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), &buf_fcolor[0].c[0]);CHECKGLERROR + } + else + { + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), &buf_bcolor[0].c[0]);CHECKGLERROR + } + glEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR + + if (backendunits > 1) + { + for (i = 0;i < backendunits;i++) + { + qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR + glBindTexture(GL_TEXTURE_2D, mesh_texture[i]);CHECKGLERROR + glDisable(GL_TEXTURE_2D);CHECKGLERROR + if (gl_combine.integer) + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, mesh_texturergbscale[i]);CHECKGLERROR + glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);CHECKGLERROR + } + else + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR + } + + qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR + glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);CHECKGLERROR + glEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR + } + } + else + { + glBindTexture(GL_TEXTURE_2D, (mesh_texture[0] = 0));CHECKGLERROR + glDisable(GL_TEXTURE_2D);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR + + glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);CHECKGLERROR + glEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR + } +} // renders mesh buffers, called to flush buffers when full void R_Mesh_Render(void) { - int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, endtriangle, indexcount, firstvert, endvert, texture[MAX_TEXTUREUNITS]; - float farclip, texturergbscale[MAX_TEXTUREUNITS]; + int i; + int k; + int firsttriangle; + int endtriangle; + int indexcount; + int firstvert; + int endvert; + float farclip; buf_mesh_t *mesh; unsigned int *index; // float to byte color conversion int *icolor; float *fcolor; qbyte *bcolor; + if (!backendactive) Sys_Error("R_Mesh_Render: called when backend is not active\n"); + if (!currentmesh) return; -CHECKGLERROR + CHECKGLERROR // push out farclip based on vertices + // FIXME: wouldn't this be a little slow when using matrix transforms? for (i = 0;i < currentvertex;i++) { farclip = DotProduct(buf_vertex[i].v, vpn); @@ -386,37 +540,7 @@ CHECKGLERROR if (farclip > r_newfarclip) r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256; - for (i = 0;i < backendunits;i++) - texturergbscale[i] = 1; - - glEnable(GL_CULL_FACE); -CHECKGLERROR - glCullFace(GL_FRONT); -CHECKGLERROR - depthtest = true; - glEnable(GL_DEPTH_TEST); -CHECKGLERROR - blendfunc1 = GL_ONE; - blendfunc2 = GL_ZERO; - glBlendFunc(blendfunc1, blendfunc2); -CHECKGLERROR - blend = 0; - glDisable(GL_BLEND); -CHECKGLERROR - depthmask = true; - glDepthMask((GLboolean) depthmask); -CHECKGLERROR - - glVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), &buf_vertex[0].v[0]); -CHECKGLERROR - glEnableClientState(GL_VERTEX_ARRAY); -CHECKGLERROR - if (gl_mesh_floatcolors.integer) - { - glColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), &buf_fcolor[0].c[0]); -CHECKGLERROR - } - else + if (!gl_mesh_floatcolors.integer) { // shift float to have 8bit fraction at base of number for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++) @@ -434,230 +558,118 @@ CHECKGLERROR k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k; k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k; } - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), &buf_bcolor[0].c[0]); -CHECKGLERROR - } - glEnableClientState(GL_COLOR_ARRAY); -CHECKGLERROR - - if (backendunits > 1) - { - for (i = 0;i < backendunits;i++) - { - qglActiveTexture(GL_TEXTURE0_ARB + (unit = i)); -CHECKGLERROR - glBindTexture(GL_TEXTURE_2D, (texture[i] = 0)); -CHECKGLERROR - glDisable(GL_TEXTURE_2D); -CHECKGLERROR - if (gl_combine.integer) - { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA); -CHECKGLERROR - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); -CHECKGLERROR - glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f); -CHECKGLERROR - } - else - { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -CHECKGLERROR - } - - qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i)); -CHECKGLERROR - glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]); -CHECKGLERROR - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR - } - } - else - { - glBindTexture(GL_TEXTURE_2D, (texture[0] = 0)); -CHECKGLERROR - glDisable(GL_TEXTURE_2D); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -CHECKGLERROR - - glTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]); -CHECKGLERROR - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR } - // lock as early as possible - GL_LockArray(0, currentvertex); -CHECKGLERROR + // lock the arrays now that they will have no further modifications + //GL_LockArray(0, currentvertex);CHECKGLERROR for (k = 0, mesh = buf_mesh;k < currentmesh;k++, mesh++) { if (backendunits > 1) { -// int topunit = 0; for (i = 0;i < backendunits;i++) { - if (texture[i] != mesh->textures[i]) + if (mesh_texture[i] != mesh->textures[i]) { - if (unit != i) + if (mesh_unit != i) { - qglActiveTexture(GL_TEXTURE0_ARB + (unit = i)); -CHECKGLERROR + qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR } - if (texture[i] == 0) + if (mesh_texture[i] == 0) { - glEnable(GL_TEXTURE_2D); -CHECKGLERROR + glEnable(GL_TEXTURE_2D);CHECKGLERROR // have to disable texcoord array on disabled texture // units due to NVIDIA driver bug with // compiled_vertex_array - if (clientunit != i) + if (mesh_clientunit != i) { - qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i)); -CHECKGLERROR + qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR } - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + glEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } - glBindTexture(GL_TEXTURE_2D, (texture[i] = mesh->textures[i])); -CHECKGLERROR - if (texture[i] == 0) + glBindTexture(GL_TEXTURE_2D, (mesh_texture[i] = mesh->textures[i]));CHECKGLERROR + if (mesh_texture[i] == 0) { - glDisable(GL_TEXTURE_2D); -CHECKGLERROR + glDisable(GL_TEXTURE_2D);CHECKGLERROR // have to disable texcoord array on disabled texture // units due to NVIDIA driver bug with // compiled_vertex_array - if (clientunit != i) + if (mesh_clientunit != i) { - qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i)); -CHECKGLERROR + qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + glDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } } - if (texturergbscale[i] != mesh->texturergbscale[i]) + if (mesh_texturergbscale[i] != mesh->texturergbscale[i]) { - if (unit != i) + if (mesh_unit != i) { - qglActiveTexture(GL_TEXTURE0_ARB + (unit = i)); -CHECKGLERROR + qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR } - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (texturergbscale[i] = mesh->texturergbscale[i])); -CHECKGLERROR + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (mesh_texturergbscale[i] = mesh->texturergbscale[i]));CHECKGLERROR } -// if (texture[i]) -// topunit = i; } -// if (unit != topunit) -// { -// qglActiveTexture(GL_TEXTURE0_ARB + (unit = topunit)); -//CHECKGLERROR -// } } else { - if (texture[0] != mesh->textures[0]) + if (mesh_texture[0] != mesh->textures[0]) { - if (texture[0] == 0) + if (mesh_texture[0] == 0) { - glEnable(GL_TEXTURE_2D); -CHECKGLERROR - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + glEnable(GL_TEXTURE_2D);CHECKGLERROR + glEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } - glBindTexture(GL_TEXTURE_2D, (texture[0] = mesh->textures[0])); -CHECKGLERROR - if (texture[0] == 0) + glBindTexture(GL_TEXTURE_2D, (mesh_texture[0] = mesh->textures[0]));CHECKGLERROR + if (mesh_texture[0] == 0) { - glDisable(GL_TEXTURE_2D); -CHECKGLERROR - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + glDisable(GL_TEXTURE_2D);CHECKGLERROR + glDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } } } - if (blendfunc1 != mesh->blendfunc1 || blendfunc2 != mesh->blendfunc2) + if (mesh_blendfunc1 != mesh->blendfunc1 || mesh_blendfunc2 != mesh->blendfunc2) { - blendfunc1 = mesh->blendfunc1; - blendfunc2 = mesh->blendfunc2; - glBlendFunc(blendfunc1, blendfunc2); -CHECKGLERROR - if (blendfunc2 == GL_ZERO) + glBlendFunc(mesh_blendfunc1 = mesh->blendfunc1, mesh_blendfunc2 = mesh->blendfunc2);CHECKGLERROR + if (mesh_blendfunc2 == GL_ZERO) { - if (blendfunc1 == GL_ONE) + if (mesh_blendfunc1 == GL_ONE) { - if (blend) + if (mesh_blend) { - blend = 0; - glDisable(GL_BLEND); -CHECKGLERROR + mesh_blend = 0; + glDisable(GL_BLEND);CHECKGLERROR } } else { - if (!blend) + if (!mesh_blend) { - blend = 1; - glEnable(GL_BLEND); -CHECKGLERROR + mesh_blend = 1; + glEnable(GL_BLEND);CHECKGLERROR } } } else { - if (!blend) + if (!mesh_blend) { - blend = 1; - glEnable(GL_BLEND); -CHECKGLERROR + mesh_blend = 1; + glEnable(GL_BLEND);CHECKGLERROR } } } - if (depthtest != mesh->depthtest) + if (mesh_depthtest != mesh->depthtest) { - depthtest = mesh->depthtest; - if (depthtest) + mesh_depthtest = mesh->depthtest; + if (mesh_depthtest) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); } - if (depthmask != mesh->depthmask) + if (mesh_depthmask != mesh->depthmask) { - depthmask = mesh->depthmask; - glDepthMask((GLboolean) depthmask); -CHECKGLERROR + glDepthMask(mesh_depthmask = mesh->depthmask);CHECKGLERROR } firsttriangle = mesh->firsttriangle; @@ -667,79 +679,82 @@ CHECKGLERROR indexcount = (endtriangle - firsttriangle) * 3; index = (unsigned int *)&buf_tri[firsttriangle].index[0]; - for (i = 0;i < indexcount;i++) - index[i] += firstvert; + // if not using batching, skip the index adjustment + if (firstvert != 0) + for (i = 0;i < indexcount;i++) + index[i] += firstvert; + + // lock arrays (this is ignored if already locked) + CHECKGLERROR + GL_LockArray(0, currentvertex); #ifdef WIN32 // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32 - glDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index); + glDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);CHECKGLERROR #else - glDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index); + glDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);CHECKGLERROR #endif -CHECKGLERROR } currentmesh = 0; currenttriangle = 0; currentvertex = 0; - GL_UnlockArray(); -CHECKGLERROR + GL_UnlockArray();CHECKGLERROR +} + +// restores backend state, used when done with 3D rendering +void R_Mesh_Finish(void) +{ + int i; + // flush any queued meshs + R_Mesh_Render(); if (backendunits > 1) { for (i = backendunits - 1;i >= 0;i--) { - qglActiveTexture(GL_TEXTURE0_ARB + (unit = i)); -CHECKGLERROR - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -CHECKGLERROR + qglActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR if (gl_combine.integer) { - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); -CHECKGLERROR + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);CHECKGLERROR } if (i > 0) { - glDisable(GL_TEXTURE_2D); -CHECKGLERROR + glDisable(GL_TEXTURE_2D);CHECKGLERROR } else { - glEnable(GL_TEXTURE_2D); -CHECKGLERROR + glEnable(GL_TEXTURE_2D);CHECKGLERROR } - glBindTexture(GL_TEXTURE_2D, 0); -CHECKGLERROR + glBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR - qglClientActiveTexture(GL_TEXTURE0_ARB + (clientunit = i)); -CHECKGLERROR - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + qglClientActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR + glDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } } else { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -CHECKGLERROR - glEnable(GL_TEXTURE_2D); -CHECKGLERROR - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -CHECKGLERROR + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR + glEnable(GL_TEXTURE_2D);CHECKGLERROR + glDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } - glDisableClientState(GL_COLOR_ARRAY); -CHECKGLERROR - glDisableClientState(GL_VERTEX_ARRAY); -CHECKGLERROR - - glDisable(GL_BLEND); -CHECKGLERROR - glEnable(GL_DEPTH_TEST); -CHECKGLERROR - glDepthMask(true); -CHECKGLERROR - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -CHECKGLERROR + glDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR + glDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR + + glDisable(GL_BLEND);CHECKGLERROR + glEnable(GL_DEPTH_TEST);CHECKGLERROR + glDepthMask(true);CHECKGLERROR + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR +} + +void R_Mesh_ClearDepth(void) +{ + R_Mesh_AddTransparent(); + R_Mesh_Finish(); + glClear(GL_DEPTH_BUFFER_BIT); + R_Mesh_Start(); } void R_Mesh_AddTransparent(void) @@ -1366,14 +1381,14 @@ void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts) ============================================================================== */ -float CalcFov (float fov_x, float width, float height); -void R_ClearScreen(void); - void SCR_ScreenShot(char *filename, int x, int y, int width, int height) { int i; qbyte *buffer; + if (!r_render.integer) + return; + buffer = Mem_Alloc(tempmempool, width*height*3); glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); CHECKGLERROR @@ -1388,126 +1403,25 @@ void SCR_ScreenShot(char *filename, int x, int y, int width, int height) Mem_Free(buffer); } -/* -================== -SCR_ScreenShot_f -================== -*/ -void SCR_ScreenShot_f (void) -{ - int i; - char filename[16]; - char checkname[MAX_OSPATH]; -// -// find a file name to save it to -// - strcpy(filename, "dp0000.tga"); - - for (i=0 ; i<=9999 ; i++) - { - filename[2] = (i/1000)%10 + '0'; - filename[3] = (i/ 100)%10 + '0'; - filename[4] = (i/ 10)%10 + '0'; - filename[5] = (i/ 1)%10 + '0'; - sprintf (checkname, "%s/%s", com_gamedir, filename); - if (Sys_FileTime(checkname) == -1) - break; // file doesn't exist - } - if (i==10000) - { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); - return; - } - - SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight); - Con_Printf ("Wrote %s\n", filename); -} - -/* -=============== -R_Envmap_f - -Grab six views for environment mapping tests -=============== -*/ -struct -{ - float angles[3]; - char *name; -} -envmapinfo[6] = -{ - {{ 0, 0, 0}, "ft"}, - {{ 0, 90, 0}, "rt"}, - {{ 0, 180, 0}, "bk"}, - {{ 0, 270, 0}, "lf"}, - {{-90, 90, 0}, "up"}, - {{ 90, 90, 0}, "dn"} -}; -static void R_Envmap_f (void) -{ - int j, size; - char filename[256], basename[256]; - - if (Cmd_Argc() != 3) - { - Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); - return; - } - - if (!r_render.integer) - return; - - strcpy(basename, Cmd_Argv(1)); - size = atoi(Cmd_Argv(2)); - if (size != 128 && size != 256 && size != 512 && size != 1024) - { - Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); - return; - } - if (size > vid.realwidth || size > vid.realheight) - { - Con_Printf("envmap: your resolution is not big enough to render that size\n"); - return; - } - - envmap = true; - - r_refdef.x = 0; - r_refdef.y = 0; - r_refdef.width = size; - r_refdef.height = size; - - r_refdef.fov_x = 90; - r_refdef.fov_y = 90; - - for (j = 0;j < 6;j++) - { - sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name); - VectorCopy(envmapinfo[j].angles, r_refdef.viewangles); - R_ClearScreen(); - R_RenderView (); - SCR_ScreenShot(filename, vid.realx, vid.realy, size, size); - } - - envmap = false; -} - //============================================================================= void R_ClearScreen(void) { if (r_render.integer) { - glClearColor(0,0,0,0); - CHECKGLERROR - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) - CHECKGLERROR + // clear to black + glClearColor(0,0,0,0);CHECKGLERROR + // clear the screen + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);CHECKGLERROR + // set dithering mode if (gl_dither.integer) - glEnable(GL_DITHER); + { + glEnable(GL_DITHER);CHECKGLERROR + } else - glDisable(GL_DITHER); - CHECKGLERROR + { + glDisable(GL_DITHER);CHECKGLERROR + } } } diff --git a/gl_backend.h b/gl_backend.h index 1c0be7bd..450409ee 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -1,5 +1,5 @@ -#define MAX_TEXTUREUNITS 4 +#define MAX_TEXTUREUNITS 8 extern int c_meshtris, c_meshs, c_transtris, c_transmeshs; @@ -49,18 +49,46 @@ rmeshbufferinfo_t; // adds console variables and registers the render module (only call from GL_Init) void gl_backend_init(void); -// sets up mesh renderer for the frame -void R_Mesh_Clear(void); -// renders queued meshs + +// starts mesh rendering for the frame +void R_Mesh_Start(void); + +// ends mesh rendering for the frame +// (only valid after R_Mesh_Start) +void R_Mesh_Finish(void); + +// clears depth buffer, used for masked sky rendering +// (only valid between R_Mesh_Start and R_Mesh_Finish) +void R_Mesh_ClearDepth(void); + +// renders current batch of meshs +// (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_Render(void); + // queues a mesh to be rendered (invokes Render if queue is full) +// (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_Draw(const rmeshinfo_t *m); + // renders the queued transparent meshs +// (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_AddTransparent(void); + // ease-of-use frontend to R_Mesh_Draw, set up meshinfo, except for index and numtriangles and numverts, then call this +// (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts); + // same as normal, except for harsh format restrictions (vertex must be 4 float, color must be 4 float, texcoord must be 2 float, flat color not supported) +// (only valid between R_Mesh_Start and R_Mesh_Finish) void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m); + // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct // (this is used for very high speed rendering, no copying) +// (only valid between R_Mesh_Start and R_Mesh_Finish) int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m); + +// saves a section of the rendered frame to a .tga file +void SCR_ScreenShot(char *filename, int x, int y, int width, int height); +// used by R_Envmap_f and internally in backend, clears the frame +void R_ClearScreen(void); +// invoke refresh of frame +void SCR_UpdateScreen (void); diff --git a/gl_models.c b/gl_models.c index 55eadf2b..3c83354b 100644 --- a/gl_models.c +++ b/gl_models.c @@ -2,7 +2,6 @@ #include "quakedef.h" //cvar_t gl_transform = {0, "gl_transform", "1"}; -cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"}; typedef struct { @@ -21,25 +20,6 @@ rmeshinfo_t aliasmeshinfo; rtexture_t *chrometexture; -int arraylocked = false; -void GL_LockArray(int first, int count) -{ - if (gl_supportslockarrays && gl_lockarrays.integer) - { - qglLockArraysEXT(first, count); - arraylocked = true; - } -} - -void GL_UnlockArray(void) -{ - if (arraylocked) - { - qglUnlockArraysEXT(); - arraylocked = false; - } -} - /* void GL_SetupModelTransform (vec3_t origin, vec3_t angles, vec_t scale) { @@ -106,7 +86,6 @@ void gl_models_newmap(void) void GL_Models_Init(void) { // Cvar_RegisterVariable(&gl_transform); - Cvar_RegisterVariable(&gl_lockarrays); R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap); } diff --git a/gl_rmain.c b/gl_rmain.c index 78a04448..845c87f7 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -611,7 +611,7 @@ r_refdef must be set before the first call void R_RenderView (void) { if (!cl.worldmodel) - Host_Error ("R_RenderView: NULL worldmodel"); + return; //Host_Error ("R_RenderView: NULL worldmodel"); // FIXME: move to client R_MoveExplosions(); @@ -625,7 +625,7 @@ void R_RenderView (void) R_Clip_StartFrame(); R_BuildLightList(); - R_Mesh_Clear(); + R_Mesh_Start(); R_TimeReport("setup"); @@ -700,8 +700,8 @@ void R_RenderView (void) R_TimeReport("blendview"); // render any queued meshs - R_Mesh_Render(); - R_TimeReport("meshrender"); + R_Mesh_Finish(); + R_TimeReport("meshfinish"); //Mem_CheckSentinelsGlobal(); //R_TimeReport("memtest"); diff --git a/host.c b/host.c index 0f8987ec..88ef16a6 100644 --- a/host.c +++ b/host.c @@ -142,7 +142,7 @@ void Host_Error (char *error, ...) } inerror = true; -// SCR_EndLoadingPlaque (); // reenable screen updates + SCR_EndLoadingPlaque (); // reenable screen updates va_start (argptr,error); vsprintf (hosterrorstring,error,argptr); diff --git a/host_cmd.c b/host_cmd.c index 226b1f13..3934de44 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -266,7 +266,7 @@ void Host_Map_f (void) cls.demonum = -1; // stop demo loop in case this fails -// SCR_BeginLoadingPlaque (); + SCR_BeginLoadingPlaque (); CL_Disconnect (); Host_ShutdownServer(false); @@ -358,7 +358,7 @@ This is sent just before a server changes levels */ void Host_Reconnect_f (void) { -// SCR_BeginLoadingPlaque (); + SCR_BeginLoadingPlaque (); cls.signon = 0; // need new connection messages } @@ -396,7 +396,7 @@ LOAD / SAVE GAME =============== Host_SavegameComment -Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current +Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current =============== */ void Host_SavegameComment (char *text) @@ -461,7 +461,7 @@ void Host_Savegame_f (void) Con_Printf ("Relative pathnames are not allowed.\n"); return; } - + for (i=0 ; iv.health <= 0) ) @@ -473,7 +473,7 @@ void Host_Savegame_f (void) sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); COM_DefaultExtension (name, ".sav"); - + Con_Printf ("Saving game to %s...\n", name); f = Qopen (name, "w"); if (!f) @@ -481,7 +481,7 @@ void Host_Savegame_f (void) Con_Printf ("ERROR: couldn't open.\n"); return; } - + Qprintf (f, "%i\n", SAVEGAME_VERSION); Host_SavegameComment (comment); Qprintf (f, "%s\n", comment); @@ -564,6 +564,9 @@ void Host_Loadgame_f (void) Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); return; } + + SCR_BeginLoadingPlaque (); + str = Qgetline (f); for (i=0 ; i