From 946b5d6f5210b4b355ff6819710da9d23560803d Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 25 Feb 2011 04:22:14 +0000 Subject: [PATCH] lots of useless stuff. will attempt to load doom3 maps. _gl_fog 1 and friends can be used to activate fog, still needs tweeks for use, not a final feature at all. added gl_screenangle which rotates the screen, including hud. seems to be some nvidia driver issue. may need end-tasking after video shuts down (including from-fullscreen vid_restarts). double-frees on glsl shaders is now supposedly fixed. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3735 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_screen.c | 19 +- engine/client/console.c | 2 +- engine/client/image.c | 2 +- engine/client/m_mp3.c | 2 +- engine/client/merged.h | 5 +- engine/client/p_script.c | 2 +- engine/client/pr_csqc.c | 2 +- engine/client/r_2d.c | 37 +++- engine/client/r_surf.c | 52 ++++- engine/client/render.h | 15 +- engine/client/renderer.c | 3 + engine/client/sbar.c | 2 +- engine/client/vid.h | 10 +- engine/client/view.c | 2 +- engine/common/bothdefs.h | 2 +- engine/common/cmd.c | 4 +- engine/common/common.c | 65 +++--- engine/common/common.h | 2 +- engine/common/fs.c | 3 + engine/common/pr_bgcmd.c | 2 +- engine/common/q3common.c | 6 +- engine/d3d/d3d_backend.c | 2 +- engine/d3d/vid_d3d.c | 5 + engine/gl/gl_backend.c | 445 +++++++++++++++++++++++++++----------- engine/gl/gl_bloom.c | 19 +- engine/gl/gl_draw.c | 88 +++++--- engine/gl/gl_font.c | 40 ++-- engine/gl/gl_heightmap.c | 4 +- engine/gl/gl_hlmdl.c | 2 +- engine/gl/gl_model.c | 6 +- engine/gl/gl_model.h | 17 +- engine/gl/gl_ngraph.c | 4 +- engine/gl/gl_rmain.c | 33 +-- engine/gl/gl_rmisc.c | 7 +- engine/gl/gl_rsurf.c | 50 +++-- engine/gl/gl_shader.c | 427 ++++++++++++++++++++++++++---------- engine/gl/gl_shadow.c | 14 +- engine/gl/gl_warp.c | 4 +- engine/gl/glquake.h | 8 +- engine/gl/shader.h | 31 ++- engine/qclib/pr_edict.c | 14 ++ engine/server/sv_ccmds.c | 8 +- engine/server/sv_init.c | 3 + 43 files changed, 1036 insertions(+), 434 deletions(-) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index ff8c0fcf..c1e92088 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -67,14 +67,21 @@ void RSpeedShow(void) RQntNames[RQUANT_MSECS] = "Microseconds"; RQntNames[RQUANT_EPOLYS] = "Entity Polys"; RQntNames[RQUANT_WPOLYS] = "World Polys"; + RQntNames[RQUANT_DRAWS] = "Draw Calls"; + RQntNames[RQUANT_2DBATCHES] = "2d Batches"; + RQntNames[RQUANT_WORLDBATCHES] = "World Batches"; + RQntNames[RQUANT_ENTBATCHES] = "Ent Batches"; RQntNames[RQUANT_SHADOWFACES] = "Shadow Faces"; RQntNames[RQUANT_SHADOWEDGES] = "Shadow edges"; RQntNames[RQUANT_LITFACES] = "Lit faces"; - for (i = 0; i < RSPEED_MAX; i++) + if (r_speeds.ival > 1) { - s = va("%i %-20s", samplerspeeds[i], RSpNames[i]); - Draw_FunString(vid.width-strlen(s)*8, i*8, s); + for (i = 0; i < RSPEED_MAX; i++) + { + s = va("%i %-20s", samplerspeeds[i], RSpNames[i]); + Draw_FunString(vid.width-strlen(s)*8, i*8, s); + } } for (i = 0; i < RQUANT_MAX; i++) { @@ -84,7 +91,7 @@ void RSpeedShow(void) s = va("%f %-20s", 100000000.0f/samplerspeeds[RSPEED_TOTALREFRESH], "Framerate"); Draw_FunString(vid.width-strlen(s)*8, (i+RSPEED_MAX)*8, s); - if (framecount++>=100) + if (++framecount>=100) { for (i = 0; i < RSPEED_MAX; i++) { @@ -1286,6 +1293,10 @@ void SCR_DrawFPS (void) SCR_StringXY(va("%f deviation", deviation), show_fps_x.value, show_fps_y.value-8); } break; + case 8: + if (cls.timedemo) + Con_Printf("%f\n", frametime); + break; } if (usemsecs) diff --git a/engine/client/console.c b/engine/client/console.c index 1f4d0efa..9121934c 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1379,7 +1379,7 @@ void Con_DrawConsole (int lines, qboolean noback) selstartoffset = 0; } - Draw_Fill((sstart*vid.width)/vid.pixelwidth, (y*vid.height)/vid.pixelheight, ((send - sstart)*vid.width)/vid.pixelwidth, (Font_CharHeight()*vid.height)/vid.pixelheight, 0); + Draw_Fill((sstart*vid.width)/vid.rotpixelwidth, (y*vid.height)/vid.rotpixelheight, ((send - sstart)*vid.width)/vid.rotpixelwidth, (Font_CharHeight()*vid.height)/vid.rotpixelheight, 0); } } } diff --git a/engine/client/image.c b/engine/client/image.c index fdf460f0..8684ab26 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -2124,7 +2124,7 @@ texid_t GL_LoadTextureDDS(unsigned char *buffer, int filesize) return r_nulltex; texnum = GL_AllocNewTexture(fmtheader.dwWidth, fmtheader.dwHeight); - GL_Bind(texnum); + GL_MTBind(0, GL_TEXTURE_2D, texnum); datasize = fmtheader.dwPitchOrLinearSize; for (mipnum = 0; mipnum < nummips; mipnum++) diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 0042da84..a4a84dcf 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2039,7 +2039,7 @@ static int MSD_GetDMAPos(soundcardinfo_t *sc) return s; } -static void MSD_Submit(soundcardinfo_t *sc) +static void MSD_Submit(soundcardinfo_t *sc, int start, int end) { //Fixme: support outputting to wav //http://www.borg.com/~jglatt/tech/wave.htm diff --git a/engine/client/merged.h b/engine/client/merged.h index d4f457f6..1ae403cd 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -168,9 +168,10 @@ typedef enum backendmode_e BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps). BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer. BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal. - BEM_LIGHT, //we have a valid light + BEM_LIGHT, //we have a valid light BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap - BEM_SMAPLIGHT //we have a light using a shadowmap + BEM_SMAPLIGHT, //we have a light using a shadowmap + BEM_FOG //drawing a fog volume } backendmode_t; typedef struct rendererinfo_s { diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 8549cb59..03154c34 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -1433,7 +1433,7 @@ static void P_ImportEffectInfo_f(void) Con_Printf("Too many args!\n"); args--; } - line = COM_StringParse(line, false, false); + line = COM_StringParse(line, com_token, sizeof(com_token), false, false); Q_strncpyz(arg[args], com_token, sizeof(arg[args])); args++; if (*com_token == '\n') diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index ed689336..2547f2ba 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -704,8 +704,8 @@ static void QCBUILTIN PF_cs_makestatic (progfuncs_t *prinst, struct globalvars_s ent = &cl_static_entities[cl.num_statics].ent; if (CopyCSQCEdictToEntity(in, ent)) { - cl.num_statics++; cl_static_entities[cl.num_statics].mdlidx = in->v->modelindex; + cl.num_statics++; } PF_cs_remove(prinst, pr_globals); diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index eb0e46bd..31e58dd9 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -22,11 +22,13 @@ extern cvar_t scr_conalpha; extern cvar_t gl_conback; extern cvar_t gl_font; extern cvar_t gl_contrast; +extern cvar_t gl_screenangle; extern cvar_t vid_conautoscale; extern cvar_t vid_conheight; extern cvar_t vid_conwidth; void R2D_Font_Callback(struct cvar_s *var, char *oldvalue); void R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue); +void R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue); void R2D_Conheight_Callback(struct cvar_s *var, char *oldvalue); void R2D_Conwidth_Callback(struct cvar_s *var, char *oldvalue); @@ -128,6 +130,7 @@ void R2D_Init(void) Cvar_Hook(&gl_font, R2D_Font_Callback); Cvar_Hook(&vid_conautoscale, R2D_Conautoscale_Callback); + Cvar_Hook(&gl_screenangle, R2D_ScreenAngle_Callback); Cvar_Hook(&vid_conheight, R2D_Conheight_Callback); Cvar_Hook(&vid_conwidth, R2D_Conwidth_Callback); @@ -383,9 +386,9 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) return; } - font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, var->string); + font_conchar = Font_LoadFont(8*vid.rotpixelheight/vid.height, var->string); if (!font_conchar && *var->string) - font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, ""); + font_conchar = Font_LoadFont(8*vid.rotpixelheight/vid.height, ""); } // console size manipulation callbacks @@ -396,6 +399,23 @@ void R2D_Console_Resize(void) int cwidth, cheight; float xratio; float yratio=0; + float ang, rad; + extern cvar_t gl_screenangle; + + ang = (gl_screenangle.value>0?(gl_screenangle.value+45):(gl_screenangle.value-45))/90; + ang = (int)ang * 90; + if (ang) + { + rad = (ang * M_PI) / 180; + vid.rotpixelwidth = fabs(cos(rad)) * (vid.pixelwidth) + fabs(sin(rad)) * (vid.pixelheight); + vid.rotpixelheight = fabs(sin(rad)) * (vid.pixelwidth) + fabs(cos(rad)) * (vid.pixelheight); + } + else + { + vid.rotpixelwidth = vid.pixelwidth; + vid.rotpixelheight = vid.pixelheight; + } + cwidth = vid_conwidth.value; cheight = vid_conheight.value; @@ -413,8 +433,8 @@ void R2D_Console_Resize(void) yratio = 1 / yratio; //autoscale overrides conwidth/height (without actually changing them) - cwidth = vid.pixelwidth; - cheight = vid.pixelheight; + cwidth = vid.rotpixelwidth; + cheight = vid.rotpixelheight; } else { @@ -424,9 +444,9 @@ void R2D_Console_Resize(void) if (!cwidth) - cwidth = vid.pixelwidth; + cwidth = vid.rotpixelwidth; if (!cheight) - cheight = vid.pixelheight; + cheight = vid.rotpixelheight; cwidth*=xratio; cheight*=yratio; @@ -493,6 +513,11 @@ void R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue) R2D_Console_Resize(); } +void R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue) +{ + R2D_Console_Resize(); +} + /* ============ diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 6a9885a4..31a6a489 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1870,6 +1870,11 @@ void Surf_SetupFrame(void) } } #endif + else if (cl.worldmodel && cl.worldmodel->fromgame == fg_doom3) + { + r_viewleaf = NULL; + r_viewleaf2 = NULL; + } else { r_oldviewleaf = r_viewleaf; @@ -1945,7 +1950,7 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent) // calculate dynamic lighting for bmodel if it's not an // instanced model - if (model->fromgame != fg_quake3) + if (model->fromgame != fg_quake3 && model->fromgame != fg_doom3) { int k; int shift; @@ -2001,6 +2006,36 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent) if (ent->flags & RF_NODEPTHTEST) bef |= BEF_FORCENODEPTH; + if (!model->surfaces && model->batches) + { + for (i = 0; i < model->numsurfaces; i++) + { + b = BE_GetTempBatch(); + if (!b) + continue; + *b = model->batches[0][i]; + b->mesh = (mesh_t**)&model->batches[0][i].mesh; + b->ent = ent; + + if (bef & BEF_FORCEADDITIVE) + { + b->next = batches[SHADER_SORT_ADDITIVE]; + batches[SHADER_SORT_ADDITIVE] = b; + } + else if (bef & BEF_FORCETRANSPARENT) + { + b->next = batches[SHADER_SORT_BLEND]; + batches[SHADER_SORT_BLEND] = b; + } + else + { + b->next = batches[b->shader->sort]; + batches[b->shader->sort] = b; + } + } + return; + } + b = NULL; for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) { @@ -2117,6 +2152,11 @@ void Surf_DrawWorld (void) } else #endif + if (cl.worldmodel->fromgame == fg_doom3) + { + vis = D3_CalcVis(cl.worldmodel, r_refdef.vieworg); + } + else { //extern cvar_t temp1; if (0)//temp1.value) @@ -2155,7 +2195,7 @@ void Surf_DrawWorld (void) */ // returns a texture number and the position inside it -static int Surf_LM_AllocBlock (int w, int h, int *x, int *y) +static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) { int i, j; int best, best2; @@ -2189,6 +2229,7 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y) lightmap[texnum] = Z_Malloc(sizeof(*lightmap[texnum])); lightmap[texnum]->meshchain = NULL; lightmap[texnum]->modified = true; + lightmap[texnum]->shader = shader; // reset stainmap since it now starts at 255 memset(lightmap[texnum]->stainmaps, 255, sizeof(lightmap[texnum]->stainmaps)); @@ -2201,6 +2242,9 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y) } } + /*not required, but using one lightmap per texture can result in better texture unit switching*/ + if (lightmap[texnum]->shader != shader) + continue; best = LMBLOCK_HEIGHT; @@ -2445,7 +2489,7 @@ static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) if (currentmodel->fromgame == fg_quake3) Surf_LM_FillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); else - surf->lightmaptexturenum = Surf_LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); + surf->lightmaptexturenum = Surf_LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t, surf->texinfo->texture->shader); base = lightmap[surf->lightmaptexturenum]->lightmaps; base += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * lightmap_bytes; @@ -2490,6 +2534,8 @@ void Surf_Clear(model_t *mod) { batch_t *b; int i; + if (mod->fromgame == fg_doom3) + return;/*they're on the hunk*/ for (i = 0; i < SHADER_SORT_COUNT; i++) { while ((b = mod->batches[i])) diff --git a/engine/client/render.h b/engine/client/render.h index 2bbc2537..555d250d 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -199,6 +199,7 @@ typedef struct { qbyte lightmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; qbyte deluxmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //fixme: make seperate structure for easy disabling with less memory usage. stmap stainmaps[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. + shader_t *shader; } lightmapinfo_t; extern lightmapinfo_t **lightmap; extern int numlightmaps; @@ -460,6 +461,10 @@ enum { RQUANT_MSECS, //old r_speeds RQUANT_EPOLYS, RQUANT_WPOLYS, + RQUANT_DRAWS, + RQUANT_ENTBATCHES, + RQUANT_WORLDBATCHES, + RQUANT_2DBATCHES, RQUANT_SHADOWFACES, RQUANT_SHADOWEDGES, RQUANT_LITFACES, @@ -468,7 +473,7 @@ enum { }; int rquant[RQUANT_MAX]; -#define RQuantAdd(type,quant) rquant[type] += quant; +#define RQuantAdd(type,quant) rquant[type] += quant #if defined(NDEBUG) || !defined(_WIN32) #define RSpeedLocals() @@ -477,13 +482,13 @@ int rquant[RQUANT_MAX]; #define RSpeedEnd(spt) #else #define RSpeedLocals() int rsp -#define RSpeedMark() int rsp = r_speeds.ival?Sys_DoubleTime()*1000000:0 -#define RSpeedRemark() rsp = r_speeds.ival?Sys_DoubleTime()*1000000:0 +#define RSpeedMark() int rsp = (r_speeds.ival>1)?Sys_DoubleTime()*1000000:0 +#define RSpeedRemark() rsp = (r_speeds.ival>1)?Sys_DoubleTime()*1000000:0 #if defined(_WIN32) && defined(GLQUAKE) extern void (_stdcall *qglFinish) (void); -#define RSpeedEnd(spt) do {if(r_speeds.ival && qglFinish){qglFinish(); rspeeds[spt] += (int)(Sys_DoubleTime()*1000000) - rsp;}}while (0) +#define RSpeedEnd(spt) do {if(r_speeds.ival > 1){if(r_speeds.ival > 2 && qglFinish)qglFinish(); rspeeds[spt] += (int)(Sys_DoubleTime()*1000000) - rsp;}}while (0) #else -#define RSpeedEnd(spt) rspeeds[spt] += r_speeds.value?Sys_DoubleTime()*1000000 - rsp:0 +#define RSpeedEnd(spt) rspeeds[spt] += (r_speeds.ival>1)?Sys_DoubleTime()*1000000 - rsp:0 #endif #endif diff --git a/engine/client/renderer.c b/engine/client/renderer.c index a2abc536..3fc39605 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -339,6 +339,7 @@ cvar_t vid_desktopgamma = SCVARF ("vid_desktopgamma", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); extern cvar_t gl_dither; +cvar_t gl_screenangle = SCVAR("gl_screenangle", "0"); #endif @@ -435,6 +436,8 @@ void GLRenderer_Init(void) Cvar_Register (&gl_ati_truform_type, GRAPHICALNICETIES); Cvar_Register (&gl_ati_truform_tesselation, GRAPHICALNICETIES); + Cvar_Register (&gl_screenangle, GLRENDEREROPTIONS); + Cvar_Register (&gl_skyboxdist, GLRENDEREROPTIONS); Cvar_Register (&r_wallcolour, GLRENDEREROPTIONS); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 56059f0c..e5d46ffd 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -188,7 +188,7 @@ void Draw_FunStringWidth(int x, int y, const void *str, int width) conchar_t buffer[2048]; conchar_t *w = buffer; - width = (width*vid.pixelwidth)/vid.width; + width = (width*vid.rotpixelwidth)/vid.width; COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer), false); diff --git a/engine/client/vid.h b/engine/client/vid.h index 1f38a763..e28537cf 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -52,13 +52,15 @@ typedef struct pixel_t *colormap; // 256 * VID_GRADES size int fullbright; // index of first fullbright color - unsigned width; - unsigned height; + unsigned width; /*virtual 2d width*/ + unsigned height; /*virtual 2d height*/ int numpages; int recalc_refdef; // if true, recalc vid-based stuff - unsigned pixelwidth; - unsigned pixelheight; + unsigned rotpixelwidth; /*width after rotation in pixels*/ + unsigned rotpixelheight; /*pixel after rotation in pixels*/ + unsigned pixelwidth; /*true height in pixels*/ + unsigned pixelheight; /*true width in pixels*/ } viddef_t; extern viddef_t vid; // global video state diff --git a/engine/client/view.c b/engine/client/view.c index 19533b75..ff0b1daa 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1159,7 +1159,7 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) case 2: //horizontal bands case 3: #ifdef GLQUAKE - if (qrenderer == QR_OPENGL && vid.pixelwidth > vid.pixelheight * 2 + if (qrenderer == QR_OPENGL && vid.rotpixelwidth > vid.rotpixelheight * 2 #ifdef FISH && ffov.value >= 0 #endif diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 6167b443..3445b518 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -160,7 +160,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define HUFFNETWORK //huffman network compression //#define DOOMWADS //doom wad/sprite support //#define MAP_DOOM //doom map support - //#define MAP_PROC //doom3/quake4 map support + #define MAP_PROC //doom3/quake4 map support //#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet) #define Q2BSPS //quake 2 bsp support #define Q3BSPS //quake 3 bsp support diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 5ba50e87..b66f42c5 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -1086,7 +1086,7 @@ void Cmd_ShiftArgs (int ammount, qboolean expandstring) if (cmd_args) { - cmd_args = COM_StringParse(cmd_args, expandstring, false); + cmd_args = COM_StringParse(cmd_args, com_token, sizeof(com_token), expandstring, false); if (cmd_args) while(*cmd_args == ' ' || *cmd_args == '\t') cmd_args++; @@ -1372,7 +1372,7 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize) Cmd_Args_Set(text); } - text = COM_StringParse (text, expandmacros, qctokenize); + text = COM_StringParse (text, com_token, sizeof(com_token), expandmacros, qctokenize); if (!text) return; diff --git a/engine/common/common.c b/engine/common/common.c index 02d43e40..00756bf1 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -2425,6 +2425,21 @@ skipwhite: } } +//skip / * comments + if (c == '/' && data[1] == '*') + { + data+=2; + while(*data) + { + if (*data == '*' && data[1] == '/') + { + data+=2; + goto skipwhite; + } + data++; + } + goto skipwhite; + } // handle quoted strings specially if (c == '\"') @@ -2469,14 +2484,14 @@ skipwhite: } //same as COM_Parse, but parses two quotes next to each other as a single quote as part of the string -char *COM_StringParse (const char *data, qboolean expandmacros, qboolean qctokenize) +char *COM_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize) { int c; int len; char *s; len = 0; - com_token[0] = 0; + token[0] = 0; if (!data) return NULL; @@ -2491,8 +2506,8 @@ skipwhite: } if (c == '\n') { - com_token[len++] = c; - com_token[len] = 0; + token[len++] = c; + token[len] = 0; return (char*)data+1; } @@ -2530,9 +2545,9 @@ skipwhite: data++; while (1) { - if (len >= TOKENSIZE-1) + if (len >= tokenlen-1) { - com_token[len] = '\0'; + token[len] = '\0'; return (char*)data; } @@ -2543,12 +2558,12 @@ skipwhite: c = *(data); if (c!='\"') { - com_token[len] = 0; + token[len] = 0; return (char*)data; } while (c=='\"') { - com_token[len] = c; + token[len] = c; len++; data++; c = *(data+1); @@ -2556,10 +2571,10 @@ skipwhite: } if (!c) { - com_token[len] = 0; + token[len] = 0; return (char*)data-1; } - com_token[len] = c; + token[len] = c; len++; } } @@ -2570,9 +2585,9 @@ skipwhite: data++; while (1) { - if (len >= TOKENSIZE-1) + if (len >= tokenlen-1) { - com_token[len] = '\0'; + token[len] = '\0'; return (char*)data; } @@ -2583,12 +2598,12 @@ skipwhite: c = *(data); if (c!='\'') { - com_token[len] = 0; + token[len] = 0; return (char*)data; } while (c=='\'') { - com_token[len] = c; + token[len] = c; len++; data++; c = *(data+1); @@ -2596,10 +2611,10 @@ skipwhite: } if (!c) { - com_token[len] = 0; + token[len] = 0; return (char*)data; } - com_token[len] = c; + token[len] = c; len++; } } @@ -2607,33 +2622,33 @@ skipwhite: if (qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';')) { // single character - com_token[len++] = c; - com_token[len] = 0; + token[len++] = c; + token[len] = 0; return (char*)data+1; } // parse a regular word do { - if (len >= TOKENSIZE-1) + if (len >= tokenlen-1) { - com_token[len] = '\0'; + token[len] = '\0'; return (char*)data; } - com_token[len] = c; + token[len] = c; data++; len++; c = *data; } while ((unsigned)c>32 && !(qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';'))); - com_token[len] = 0; + token[len] = 0; if (!expandmacros) return (char*)data; //now we check for macros. - for (s = com_token, c= 0; c < len; c++, s++) //this isn't a quoted token by the way. + for (s = token, c= 0; c < len; c++, s++) //this isn't a quoted token by the way. { if (*s == '$') { @@ -2653,9 +2668,9 @@ skipwhite: macro = Cvar_FindVar(name); if (macro) //got one... { - if (len+strlen(macro->string)-(i+1) >= TOKENSIZE-1) //give up. + if (len+strlen(macro->string)-(i+1) >= tokenlen-1) //give up. { - com_token[len] = '\0'; + token[len] = '\0'; return (char*)data; } memmove(s+strlen(macro->string), s+i+1, len-c-i); diff --git a/engine/common/common.h b/engine/common/common.h index f5d2d303..5d77d28a 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -249,7 +249,7 @@ extern qboolean com_eof; char *COM_ParseOut (const char *data, char *out, int outlen); char *COM_ParseStringSet (const char *data); char *COM_ParseCString (const char *data); -char *COM_StringParse (const char *data, qboolean expandmacros, qboolean qctokenize); +char *COM_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize); char *COM_ParseToken (const char *data, const char *punctuation); char *COM_TrimString(char *str); diff --git a/engine/common/fs.c b/engine/common/fs.c index fcb39991..80563b2a 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -898,7 +898,10 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r //if we're meant to be writing, best write to it. if (strchr(mode , 'w') || strchr(mode , 'a')) + { + COM_CreatePath(fullname); return VFSOS_Open(fullname, mode); + } return NULL; } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 9581ffbe..3bb829dd 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1986,7 +1986,7 @@ int tokenizeqc(char *str, qboolean dpfuckage) break; qctoken[qctoken_count].start = str - start; - str = COM_StringParse (str, false, dpfuckage); + str = COM_StringParse (str, com_token, sizeof(com_token), false, dpfuckage); if (!str) break; diff --git a/engine/common/q3common.c b/engine/common/q3common.c index 345d282d..8bbe6bde 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -714,9 +714,9 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address ); // if( net_showpackets->integer ) - { - Con_Printf( "%s send %4i : s=%i fragment=%i,%i\n", (chan->sock == NS_CLIENT) ? "client" : "server", send.cursize, chan->outgoing_sequence, chan->reliable_start, fragmentLength ); - } +// { +// Con_Printf( "%s send %4i : s=%i fragment=%i,%i\n", (chan->sock == NS_CLIENT) ? "client" : "server", send.cursize, chan->outgoing_sequence, chan->reliable_start, fragmentLength ); +// } // Even if we have sent the whole message, // but if fragmentLength == FRAGMENTATION_TRESHOLD we have to write empty diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 397f9f3c..65bc582e 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -2179,7 +2179,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) if (batch->buildmeshes) batch->buildmeshes(batch); - else + else if (batch->texture) { batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader; batch->skin = &batch->shader->defaulttextures; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 00cb0236..02e19294 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -3,6 +3,8 @@ #include "shader.h" #include "renderque.h" +#include "glquake.h" + #ifdef D3DQUAKE #include "winquake.h" @@ -733,6 +735,9 @@ static void (D3D9_R_NewMap) (void) R_AnimateLight(); Surf_BuildLightmaps(); + if (cl.worldmodel && cl.worldmodel->fromgame == fg_doom3) + D3_GenerateAreas(cl.worldmodel); + /*wipe any lingering particles*/ P_ClearParticles(); } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 1ec165fc..540923cf 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -320,7 +320,7 @@ static const char PCFPASS_SHADER[] = "\ extern cvar_t r_glsl_offsetmapping, r_noportals; -static void BE_SendPassBlendAndDepth(unsigned int sbits); +static void BE_SendPassBlendDepthMask(unsigned int sbits); void GLBE_SubmitBatch(batch_t *batch); struct { @@ -342,6 +342,8 @@ struct { int currenttmu; int texenvmode[SHADER_PASS_MAX]; int currenttextures[SHADER_PASS_MAX]; + GLenum curtexturetype[SHADER_PASS_MAX]; + unsigned int tmuarrayactive; polyoffset_t curpolyoffset; unsigned int curcull; @@ -367,6 +369,8 @@ struct { float identitylighting; //set to how bright lightmaps should be (reduced for overbright or realtime_world_lightmaps) texid_t temptexture; + texid_t fogtexture; + float fogfar; }; //exterior state (paramters) @@ -434,11 +438,8 @@ void GL_SetShaderState2D(qboolean is2d) void GL_SelectTexture(int target) { shaderstate.currenttmu = target; - if (qglClientActiveTextureARB) - { - qglClientActiveTextureARB(target + mtexid0); + if (qglActiveTextureARB) qglActiveTextureARB(target + mtexid0); - } else if (qglSelectTextureSGIS) qglSelectTextureSGIS(target + mtexid0); } @@ -477,40 +478,83 @@ static void GL_ApplyVertexPointer(void) } } -void GL_MBind(int target, texid_t texnum) +void GL_MTBind(int tmu, int target, texid_t texnum) { - GL_SelectTexture(target); + GL_SelectTexture(tmu); #ifndef FORCESTATE - if (shaderstate.currenttextures[shaderstate.currenttmu] == texnum.num) + if (shaderstate.currenttextures[tmu] == texnum.num) return; #endif - shaderstate.currenttextures[shaderstate.currenttmu] = texnum.num; - bindTexFunc (GL_TEXTURE_2D, texnum.num); + shaderstate.currenttextures[tmu] = texnum.num; + if (target) + bindTexFunc (target, texnum.num); + + if (shaderstate.curtexturetype[tmu] != target) + { + if (shaderstate.curtexturetype[tmu]) + qglDisable(shaderstate.curtexturetype[tmu]); + shaderstate.curtexturetype[tmu] = target; + if (target) + qglEnable(target); + } + + if (((shaderstate.tmuarrayactive>>tmu) & 1) != 0) + { + qglClientActiveTextureARB(tmu + mtexid0); + if (0) + { + shaderstate.tmuarrayactive |= 1u<>tmu) & 1) != arrays) + { + qglClientActiveTextureARB(mtexid0 + tmu); + if (arrays) + { + shaderstate.tmuarrayactive |= 1u<0) { - GL_SelectTexture(--shaderstate.lastpasstmus); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } GL_SelectTexture(0); @@ -654,7 +696,7 @@ static void RevertToKnownState(void) qglColor3f(1,1,1); - shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY); + shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MASK_BITS); shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; shaderstate.shaderbits &= ~(SBITS_BLEND_BITS); @@ -695,12 +737,9 @@ void BE_SetupForShadowMap(void) { while(shaderstate.lastpasstmus>0) { - GL_SelectTexture(--shaderstate.lastpasstmus); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglShadeModel(GL_FLAT); GL_TexEnv(GL_REPLACE); qglDepthMask(GL_TRUE); @@ -711,7 +750,7 @@ void BE_SetupForShadowMap(void) } #endif -static texid_t T_Gen_CurrentRender(void) +static void T_Gen_CurrentRender(int tmu) { int vwidth, vheight; if (gl_config.arb_texture_non_power_of_two) @@ -735,51 +774,69 @@ static texid_t T_Gen_CurrentRender(void) // copy the scene to texture if (!TEXVALID(shaderstate.temptexture)) shaderstate.temptexture = GL_AllocNewTexture(vwidth, vheight); - GL_Bind(shaderstate.temptexture); + GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture); qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - return shaderstate.temptexture; } -static texid_t Shader_TextureForPass(const shaderpass_t *pass) +static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray) { + texid_t t; switch(pass->texgen) { default: + case T_GEN_SKYBOX: + t = pass->anim_frames[0]; + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); + return; case T_GEN_SINGLEMAP: - return pass->anim_frames[0]; + t = pass->anim_frames[0]; + break; case T_GEN_ANIMMAP: - return pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes]; + t = pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes]; + break; case T_GEN_LIGHTMAP: - return shaderstate.curlightmap; + t = shaderstate.curlightmap; + break; case T_GEN_DELUXMAP: - return shaderstate.curdeluxmap; + t = shaderstate.curdeluxmap; + break; case T_GEN_DIFFUSE: - return shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; + t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; + break; case T_GEN_NORMALMAP: - return shaderstate.curtexnums?shaderstate.curtexnums->bump:r_nulltex; + t = shaderstate.curtexnums?shaderstate.curtexnums->bump:r_nulltex; + break; case T_GEN_SPECULAR: - return shaderstate.curtexnums->specular; + t = shaderstate.curtexnums->specular; + break; case T_GEN_UPPEROVERLAY: - return shaderstate.curtexnums->upperoverlay; + t = shaderstate.curtexnums->upperoverlay; + break; case T_GEN_LOWEROVERLAY: - return shaderstate.curtexnums->loweroverlay; + t = shaderstate.curtexnums->loweroverlay; + break; case T_GEN_FULLBRIGHT: - return shaderstate.curtexnums->fullbright; + t = shaderstate.curtexnums->fullbright; + break; case T_GEN_SHADOWMAP: - return shaderstate.curshadowmap; + t = shaderstate.curshadowmap; + break; case T_GEN_VIDEOMAP: #ifdef NOMEDIA - return shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; + t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; #else - return Media_UpdateForShader(pass->cin); + t = Media_UpdateForShader(pass->cin); #endif + break; case T_GEN_CURRENTRENDER: - return T_Gen_CurrentRender(); + T_Gen_CurrentRender(tmu); + return; } + GL_LazyBind(tmu, GL_TEXTURE_2D, t, useclientarray); } /*========================================== matrix functions =====================================*/ @@ -871,11 +928,37 @@ void Shader_LightPass_Spot(char *shortname, shader_t *s, const void *args) Shader_DefaultScript(shortname, s, shadertext); } +texid_t GenerateFogTexture(void) +{ +#define FOGS 256 +#define FOGT 32 + byte_vec4_t fogdata[FOGS*FOGT]; + int s, t; + float f; + for(s = 0; s < FOGS; s++) + for(t = 0; t < FOGT; t++) + { + f = (float)s / FOGS; + if (f < 0) + f = 0; + if (f > 1) + f = 1; + f = pow(f, 0.5); + fogdata[t*FOGS + s][0] = 255; + fogdata[t*FOGS + s][1] = 255; + fogdata[t*FOGS + s][2] = 255; + fogdata[t*FOGS + s][3] = 255*f; + } + + return R_LoadTexture32("fog", FOGS, FOGT, fogdata, IF_CLAMP|IF_NOMIPMAP); +} + void GLBE_Init(void) { int i; double t; + shaderstate.curentity = &r_worldentity; be_maxpasses = gl_mtexarbable; for (i = 0; i < FTABLE_SIZE; i++) @@ -910,12 +993,16 @@ void GLBE_Init(void) } shaderstate.shaderbits = ~0; - BE_SendPassBlendAndDepth(0); + BE_SendPassBlendDepthMask(0); if (qglEnableClientState) qglEnableClientState(GL_VERTEX_ARRAY); currententity = &r_worldentity; + + + + shaderstate.fogtexture = GenerateFogTexture(); } //end tables @@ -954,11 +1041,36 @@ static void tcgen_environment(float *st, unsigned int numverts, float *xyz, floa } } -static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t *mesh) +static void tcgen_fog(float *st, unsigned int numverts, float *xyz) +{ + int i; + vec3_t viewer; + + vec3_t rorg; + float z; + vec4_t zmat; + + //generate a simple matrix to calc only the projected z coord + zmat[0] = -shaderstate.modelviewmatrix[2]; + zmat[1] = -shaderstate.modelviewmatrix[6]; + zmat[2] = -shaderstate.modelviewmatrix[10]; + zmat[3] = -shaderstate.modelviewmatrix[14]; + + Vector4Scale(zmat, shaderstate.fogfar, zmat); + + for (i = 0 ; i < numverts ; i++, xyz += sizeof(vecV_t)/sizeof(vec_t), st += 2 ) + { + z = DotProduct(xyz, zmat) + zmat[3]; + st[0] = z; + st[1] = realtime - (int)realtime; + } +} + +static float *tcgen(unsigned int tcgen, int cnt, float *dst, const mesh_t *mesh) { int i; vecV_t *src; - switch (pass->tcgen) + switch (tcgen) { default: case TC_GEN_BASE: @@ -976,6 +1088,9 @@ static float *tcgen(const shaderpass_t *pass, int cnt, float *dst, const mesh_t return (float*)mesh->st_array; tcgen_environment(dst, cnt, (float*)mesh->xyz_array, (float*)mesh->normals_array); return dst; + case TC_GEN_FOG: + tcgen_fog(dst, cnt, (float*)mesh->xyz_array); + return dst; // case TC_GEN_DOTPRODUCT: // return mesh->st_array[0]; @@ -1078,6 +1193,25 @@ static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, c } } +static void GenerateTCFog(int passnum) +{ + int m; + float *src; + mesh_t *mesh; + for (m = 0; m < shaderstate.meshcount; m++) + { + mesh = shaderstate.meshes[m]; + + src = tcgen(TC_GEN_FOG, mesh->numvertexes, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); + if (src != texcoordarray[passnum]+mesh->vbofirstvert*2) + { + //this shouldn't actually ever be true + memcpy(texcoordarray[passnum]+mesh->vbofirstvert*2, src, 8*mesh->numvertexes); + } + } + GL_SelectVBO(0); + qglTexCoordPointer(2, GL_FLOAT, 0, texcoordarray[passnum]); +} static void GenerateTCMods(const shaderpass_t *pass, int passnum) { #if 1 @@ -1088,7 +1222,7 @@ static void GenerateTCMods(const shaderpass_t *pass, int passnum) { mesh = shaderstate.meshes[m]; - src = tcgen(pass, mesh->numvertexes, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); + src = tcgen(pass->tcgen, mesh->numvertexes, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); //tcgen might return unmodified info if (pass->numtcmods) { @@ -1659,12 +1793,12 @@ static void GenerateColourMods(const shaderpass_t *pass) mesh_t *meshlist; meshlist = shaderstate.meshes[0]; - if (meshlist->colors4b_array) + if (shaderstate.sourcevbo->colours4ub) { //hack... - GL_SelectVBO(0); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, meshlist->colors4b_array); + GL_SelectVBO(shaderstate.sourcevbo->vbocolours); qglEnableClientState(GL_COLOR_ARRAY); + qglColorPointer(4, GL_UNSIGNED_BYTE, 0, shaderstate.sourcevbo->colours4ub); qglShadeModel(GL_SMOOTH); return; } @@ -1743,6 +1877,7 @@ static void GenerateColourMods(const shaderpass_t *pass) static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) { pass += passno; + qglClientActiveTextureARB(mtexid0 + passno); if (!pass->numtcmods) { //if there are no tcmods, pass through here as fast as possible @@ -1783,7 +1918,7 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) } } -static void BE_SendPassBlendAndDepth(unsigned int sbits) +static void BE_SendPassBlendDepthMask(unsigned int sbits) { unsigned int delta; @@ -1917,6 +2052,15 @@ static void BE_SendPassBlendAndDepth(unsigned int sbits) break; } } + if (delta & (SBITS_MASK_BITS)) + { + qglColorMask( + (sbits&SBITS_MASK_RED)?GL_FALSE:GL_TRUE, + (sbits&SBITS_MASK_GREEN)?GL_FALSE:GL_TRUE, + (sbits&SBITS_MASK_BLUE)?GL_FALSE:GL_TRUE, + (sbits&SBITS_MASK_ALPHA)?GL_FALSE:GL_TRUE + ); + } } static void BE_SubmitMeshChain(void) @@ -2011,6 +2155,7 @@ static void BE_SubmitMeshChain(void) } qglDrawRangeElements(GL_TRIANGLES, startv, endv, endi-starti, GL_INDEX_TYPE, shaderstate.sourcevbo->indicies + starti); + RQuantAdd(RQUANT_DRAWS, 1); } /* if (qglUnlockArraysEXT) @@ -2037,7 +2182,7 @@ static void DrawPass(const shaderpass_t *pass) if (i == lastpass) return; - BE_SendPassBlendAndDepth(pass[i].shaderbits); + BE_SendPassBlendDepthMask(pass[i].shaderbits); GenerateColourMods(pass+i); tmu = 0; for (; i < lastpass; i++) @@ -2048,17 +2193,10 @@ static void DrawPass(const shaderpass_t *pass) continue; if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) continue; - GL_MBind(tmu, Shader_TextureForPass(pass+i)); + Shader_BindTextureForPass(tmu, pass+i, true); BE_GeneratePassTC(pass, i); - if (tmu >= shaderstate.lastpasstmus) - { - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - switch (pass[i].blendmode) { case GL_DOT3_RGB_ARB: @@ -2088,9 +2226,7 @@ static void DrawPass(const shaderpass_t *pass) for (i = tmu; i < shaderstate.lastpasstmus; i++) { - GL_SelectTexture(i); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - qglDisable(GL_TEXTURE_2D); + GL_LazyBind(i, 0, r_nulltex, false); } shaderstate.lastpasstmus = tmu; GL_ApplyVertexPointer(); @@ -2302,68 +2438,61 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass) { const shader_t *s = shader; + program_t *p = shader->prog; int i; unsigned int attr = 0; int perm; perm = 0; - if (TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_BUMPMAP].glsl) + if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].glsl) perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->specular) && s->programhandle[perm|PERMUTATION_SPECULAR].glsl) + if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].glsl) perm |= PERMUTATION_SPECULAR; - if (TEXVALID(shaderstate.curtexnums->fullbright) && s->programhandle[perm|PERMUTATION_FULLBRIGHT].glsl) + if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].glsl) perm |= PERMUTATION_FULLBRIGHT; - if (TEXVALID(shaderstate.curtexnums->loweroverlay) && s->programhandle[perm|PERMUTATION_LOWER].glsl) + if (TEXVALID(shaderstate.curtexnums->loweroverlay) && p->handle[perm|PERMUTATION_LOWER].glsl) perm |= PERMUTATION_LOWER; - if (TEXVALID(shaderstate.curtexnums->upperoverlay) && s->programhandle[perm|PERMUTATION_UPPER].glsl) + if (TEXVALID(shaderstate.curtexnums->upperoverlay) && p->handle[perm|PERMUTATION_UPPER].glsl) perm |= PERMUTATION_UPPER; - if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_OFFSET].glsl) + if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET].glsl) perm |= PERMUTATION_OFFSET; - GL_SelectProgram(s->programhandle[perm].glsl); + GL_SelectProgram(p->handle[perm].glsl); - BE_SendPassBlendAndDepth(pass->shaderbits); + BE_SendPassBlendDepthMask(pass->shaderbits); - for (i = 0; i < s->numprogparams; i++) + for (i = 0; i < p->numparams; i++) { - if (s->progparm[i].handle[perm] == -1) + if (p->parm[i].handle[perm] == -1) continue; /*not in this permutation*/ - attr |= BE_Program_Set_Attribute(&s->progparm[i], perm); + attr |= BE_Program_Set_Attribute(&p->parm[i], perm); } - if (s->flags & SHADER_NOBUILTINATTR) + if (p->nofixedcompat) { qglDisableClientState(GL_COLOR_ARRAY); qglDisableClientState(GL_VERTEX_ARRAY); for (i = 0; i < pass->numMergedPasses; i++) { - GL_MBind(i, Shader_TextureForPass(pass+i)); + Shader_BindTextureForPass(i, pass+i, false); } - for (i = 0; i < shaderstate.lastpasstmus; i++) + //we need this loop to fix up fixed-function stuff + for (; i < shaderstate.lastpasstmus; i++) { - GL_SelectTexture(i); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - qglDisable(GL_TEXTURE_2D); + GL_LazyBind(i, 0, r_nulltex, false); } - shaderstate.lastpasstmus = 0; + shaderstate.lastpasstmus = pass->numMergedPasses; } else { GenerateColourMods(pass); for (i = 0; i < pass->numMergedPasses; i++) { - GL_MBind(i, Shader_TextureForPass(pass+i)); - if (i >= shaderstate.lastpasstmus) - { - qglEnable(GL_TEXTURE_2D); - qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + Shader_BindTextureForPass(i, pass+i, true); BE_GeneratePassTC(pass, i); } for (; i < shaderstate.lastpasstmus; i++) { - GL_SelectTexture(i); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); - qglDisable(GL_TEXTURE_2D); + GL_LazyBind(i, 0, r_nulltex, false); } shaderstate.lastpasstmus = pass->numMergedPasses; GL_ApplyVertexPointer(); @@ -2416,23 +2545,19 @@ void GLBE_SelectMode(backendmode_t mode, unsigned int flags) #ifdef RTLIGHTS if (mode == BEM_STENCIL) { - qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - /*BEM_STENCIL doesn't support mesh writing*/ qglDisableClientState(GL_COLOR_ARRAY); //disable all tmus while(shaderstate.lastpasstmus>0) { - GL_SelectTexture(--shaderstate.lastpasstmus); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } qglShadeModel(GL_FLAT); //replace mode please GL_TexEnv(GL_REPLACE); //we don't write or blend anything (maybe alpha test... but mneh) - BE_SendPassBlendAndDepth(SBITS_MISC_DEPTHCLOSERONLY); + BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS); //don't change cull stuff, and //don't actually change stencil stuff - caller needs to be @@ -2441,27 +2566,20 @@ void GLBE_SelectMode(backendmode_t mode, unsigned int flags) #endif if (mode == BEM_DEPTHONLY) { - qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ qglDisableClientState(GL_COLOR_ARRAY); while(shaderstate.lastpasstmus>0) { - GL_SelectTexture(--shaderstate.lastpasstmus); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } qglShadeModel(GL_FLAT); //we don't write or blend anything (maybe alpha test... but mneh) - BE_SendPassBlendAndDepth(SBITS_MISC_DEPTHWRITE); + BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); GL_TexEnv(GL_REPLACE); GL_CullFace(SHADER_CULL_FRONT); } - if (shaderstate.mode == BEM_STENCIL || shaderstate.mode == BEM_DEPTHONLY) - { - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } #ifdef RTLIGHTS if (mode == BEM_SMAPLIGHT) { @@ -2487,6 +2605,21 @@ void GLBE_SelectMode(backendmode_t mode, unsigned int flags) shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL); } } + if (mode == BEM_FOG) + { + while(shaderstate.lastpasstmus>0) + { + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + } + GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.fogtexture, true); + shaderstate.lastpasstmus = 1; + + qglDisableClientState(GL_COLOR_ARRAY); + qglColor4f(1, 1, 1, 1); + qglShadeModel(GL_FLAT); + GL_TexEnv(GL_MODULATE); + BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY); + } #endif } shaderstate.mode = mode; @@ -2495,7 +2628,7 @@ void GLBE_SelectMode(backendmode_t mode, unsigned int flags) void GLBE_SelectEntity(entity_t *ent) { - if (shaderstate.curentity && shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) + if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) qglDepthRange (gldepthmin, gldepthmax); shaderstate.curentity = ent; currententity = ent; @@ -2506,6 +2639,12 @@ void GLBE_SelectEntity(entity_t *ent) qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); } +void BE_SelectFog(vec3_t colour, float alpha, float fardist) +{ + qglColor4f(colour[0], colour[1], colour[2], alpha); + shaderstate.fogfar = 1/fardist; +} + #ifdef RTLIGHTS void BE_SelectDLight(dlight_t *dl, vec3_t colour) { @@ -2608,6 +2747,19 @@ static void DrawMeshes(void) int passno; passno = 0; + if (shaderstate.force2d) + { + RQuantAdd(RQUANT_2DBATCHES, 1); + } + else if (shaderstate.curentity == &r_worldentity) + { + RQuantAdd(RQUANT_WORLDBATCHES, 1); + } + else + { + RQuantAdd(RQUANT_ENTBATCHES, 1); + } + GL_SelectEBO(shaderstate.sourcevbo->vboe); if (shaderstate.curshader->numdeforms) GenerateVertexDeforms(shaderstate.curshader); @@ -2662,6 +2814,13 @@ static void DrawMeshes(void) BE_SubmitMeshChain(); break; + case BEM_FOG: + GL_DeSelectProgram(); + GenerateTCFog(0); + GL_ApplyVertexPointer(); + BE_SubmitMeshChain(); + break; + case BEM_DEPTHDARK: if (shaderstate.curshader->flags & SHADER_HASLIGHTMAP) { @@ -2670,12 +2829,10 @@ static void DrawMeshes(void) qglDisableClientState(GL_COLOR_ARRAY); while(shaderstate.lastpasstmus>0) { - GL_SelectTexture(--shaderstate.lastpasstmus); - qglDisable(GL_TEXTURE_2D); - qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } GL_TexEnv(GL_REPLACE); - BE_SendPassBlendAndDepth(shaderstate.curshader->passes[0].shaderbits); + BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); GL_ApplyVertexPointer(); BE_SubmitMeshChain(); @@ -2684,7 +2841,7 @@ static void DrawMeshes(void) //fallthrough case BEM_STANDARD: default: - if (shaderstate.curshader->programhandle[0].glsl) + if (shaderstate.curshader->prog) { BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes); } @@ -2806,6 +2963,7 @@ void GLBE_SubmitBatch(batch_t *batch) shaderstate.dummyvbo.svector = batch->mesh[0]->snormals_array; shaderstate.dummyvbo.tvector = batch->mesh[0]->tnormals_array; shaderstate.dummyvbo.colours4f = batch->mesh[0]->colors4f_array; + shaderstate.dummyvbo.colours4ub = batch->mesh[0]->colors4b_array; shaderstate.sourcevbo = &shaderstate.dummyvbo; lm = -1; } @@ -2911,9 +3069,11 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) if (batch->buildmeshes) batch->buildmeshes(batch); - else + else if (batch->texture) batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader; + if (batch->shader->flags & SHADER_NODRAW) + continue; if (batch->shader->flags & SHADER_NODLIGHT) if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT) continue; @@ -2921,7 +3081,8 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) { if (shaderstate.mode == BEM_STANDARD) R_DrawSkyChain (batch); - continue; + if (shaderstate.mode != BEM_FOG) + continue; } BE_SubmitBatch(batch); @@ -2958,7 +3119,8 @@ static void BE_UpdateLightmaps(void) glRect_t *theRect; lightmap[lm]->modified = false; theRect = &lightmap[lm]->rectchange; - GL_Bind(lightmap_textures[lm]); + checkglerror(); + GL_MTBind(0, GL_TEXTURE_2D, lightmap_textures[lm]); checkglerror(); switch (lightmap_bytes) { @@ -2988,7 +3150,7 @@ static void BE_UpdateLightmaps(void) { lightmap[lm]->deluxmodified = false; theRect = &lightmap[lm]->deluxrectchange; - GL_Bind(deluxmap_textures[lm]); + GL_MTBind(0, GL_TEXTURE_2D, deluxmap_textures[lm]); qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, lightmap[lm]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); @@ -3000,6 +3162,7 @@ static void BE_UpdateLightmaps(void) } } } + checkglerror(); } batch_t *GLBE_GetTempBatch(void) @@ -3068,6 +3231,9 @@ void GLBE_DrawWorld (qbyte *vis) extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; batch_t *batches[SHADER_SORT_COUNT]; RSpeedLocals(); + + checkglerror(); + GL_DoSwap(); if (!r_refdef.recurse) @@ -3091,7 +3257,7 @@ void GLBE_DrawWorld (qbyte *vis) shaderstate.wbatch = 0; } BE_GenModelBatches(batches); - shaderstate.curentity = NULL; + shaderstate.curentity = &r_worldentity; shaderstate.updatetime = cl.servertime; #if 0 @@ -3136,13 +3302,43 @@ void GLBE_DrawWorld (qbyte *vis) BE_DrawPolys(false); + if (1)//gl_fog.value) + { + cvar_t *v; + vec3_t rgb; + float alpha; + float fardist; + v = Cvar_Get("_gl_fog", "0", 0, "experimental"); + if (v->value) + { + v = Cvar_Get("_gl_fog_red", "1", 0, "experimental"); + rgb[0] = v->value; + v = Cvar_Get("_gl_fog_green", "1", 0, "experimental"); + rgb[1] = v->value; + v = Cvar_Get("_gl_fog_blue", "1", 0, "experimental"); + rgb[2] = v->value; + v = Cvar_Get("_gl_fog_alpha", "1", 0, "experimental"); + alpha = v->value; + v = Cvar_Get("_gl_fog_dist", "512", 0, "experimental"); + fardist = v->value; + BE_SelectMode(BEM_FOG, 0); + BE_SelectFog(rgb, alpha, fardist); + GLBE_SubmitMeshes(true, batches); + } + } + BE_SelectEntity(&r_worldentity); shaderstate.updatetime = realtime; + + checkglerror(); } void BE_DrawNonWorld (void) { batch_t *batches[SHADER_SORT_COUNT]; + + checkglerror(); + if (shaderstate.wmesh > shaderstate.maxwmesh) { int newm = shaderstate.wmesh; @@ -3162,13 +3358,14 @@ void BE_DrawNonWorld (void) shaderstate.wbatch = 0; BE_GenModelBatches(batches); - shaderstate.curentity = NULL; shaderstate.updatetime = cl.servertime; GLBE_SubmitMeshes(false, batches); BE_SelectEntity(&r_worldentity); shaderstate.updatetime = realtime; + + checkglerror(); } #endif diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 8484a2cd..15584941 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -193,7 +193,7 @@ void R_Bloom_InitTextures(void) memset(data, 255, size); if (!TEXVALID(bs.tx_screen)) bs.tx_screen = GL_AllocNewTexture(bs.scr_w, bs.scr_h); - GL_Bind(bs.tx_screen); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -255,7 +255,7 @@ R_Bloom_DrawEffect */ void R_Bloom_DrawEffect(void) { - GL_Bind(bs.tx_effect); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_effect); qglEnable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ONE); qglColor4f(r_bloom_alpha.value, r_bloom_alpha.value, r_bloom_alpha.value, 1.0f); @@ -386,7 +386,7 @@ void R_Bloom_GeneratexDiamonds(void) qglLoadIdentity(); //copy small scene into bs.tx_effect - GL_Bind(bs.tx_effect); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_effect); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); //start modifying the small scene corner @@ -459,13 +459,13 @@ void R_Bloom_DownsampleView( void ) int midsample_height = bs.size_downsample * bs.smp_t; //copy the screen and draw resized - GL_Bind(bs.tx_screen); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bs.vp_x, vid.pixelheight - (bs.vp_y + bs.vp_h), bs.vp_w, bs.vp_h); R_Bloom_Quad(0, vid.pixelheight-midsample_height, midsample_width, midsample_height, bs.scr_s, bs.scr_t); //now copy into Downsampling (mid-sized) texture - GL_Bind(bs.tx_downsample); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_downsample); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height); //now draw again in bloom size @@ -476,15 +476,14 @@ void R_Bloom_DownsampleView( void ) qglEnable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ONE); qglColor4f(0.5f, 0.5f, 0.5f, 1.0f); - GL_Bind(bs.tx_screen); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); R_Bloom_Quad(0, vid.pixelheight-bs.smp_h, bs.smp_w, bs.smp_h, bs.scr_s, bs.scr_t); qglColor4f(1.0f, 1.0f, 1.0f, 1.0f); qglDisable(GL_BLEND); } else { //downsample simple - - GL_Bind(bs.tx_screen); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bs.vp_x, vid.pixelheight - (bs.vp_y + bs.vp_h), bs.vp_w, bs.vp_h); R_Bloom_Quad(0, vid.pixelheight-bs.smp_h, bs.smp_w, bs.smp_h, bs.scr_s, bs.scr_t); } @@ -551,7 +550,7 @@ void R_BloomBlend (void) buh = bs.size_backup * bs.smp_t; //copy the screen space we'll use to work into the backup texture - GL_Bind(bs.tx_backup); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, buw, buh); //create the bloom image @@ -562,7 +561,7 @@ void R_BloomBlend (void) //restore the screen-backup to the screen qglDisable(GL_BLEND); - GL_Bind(bs.tx_backup); + GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup); qglColor4f(1, 1, 1, 1); R_Bloom_Quad(0, vid.pixelheight - (buh), diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 635af0a8..fbada1d0 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -41,7 +41,7 @@ static void GL_Upload8Pal32 (qbyte *data, qbyte *pal, int width, int height, uns void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags) { - GL_Bind(tex); + GL_MTBind(0, GL_TEXTURE_2D, tex); switch(fmt) { case TF_INVALID: @@ -220,7 +220,7 @@ void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldval { if (!(glt->flags & IF_NOMIPMAP)) { - GL_Bind (glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anfactor); } } @@ -265,7 +265,7 @@ void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue) { if (!(glt->flags & IF_NOMIPMAP)) { - GL_Bind (glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } @@ -300,7 +300,7 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue) { if (glt->flags & IF_NOMIPMAP) { - GL_Bind (glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } @@ -575,28 +575,28 @@ void GLDraw_Crosshair(void) } else { - sizex = (size*vid.pixelwidth) / (float)vid.width; - sizey = (size*vid.pixelheight) / (float)vid.height; + sizex = (size*vid.rotpixelwidth) / (float)vid.width; + sizey = (size*vid.rotpixelheight) / (float)vid.height; chc = size * chc; } sizex = (int)sizex; - sizex = ((sizex)*(int)vid.width) / (float)vid.pixelwidth; + sizex = ((sizex)*(int)vid.width) / (float)vid.rotpixelwidth; sizey = (int)sizey; - sizey = ((sizey)*(int)vid.height) / (float)vid.pixelheight; + sizey = ((sizey)*(int)vid.height) / (float)vid.rotpixelheight; for (sc = 0; sc < cl.splitclients; sc++) { SCR_CrosshairPosition(sc, &x, &y); //translate to pixel coord, for rounding - x = ((x-sizex-chc)*vid.pixelwidth) / (float)vid.width; - y = ((y-sizey-chc)*vid.pixelheight) / (float)vid.height; + x = ((x-sizex-chc)*vid.rotpixelwidth) / (float)vid.width; + y = ((y-sizey-chc)*vid.rotpixelheight) / (float)vid.height; //translate to screen coords - sx = ((x)*(int)vid.width) / (float)vid.pixelwidth; - sy = ((y)*(int)vid.height) / (float)vid.pixelheight; + sx = ((x)*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((y)*(int)vid.height) / (float)vid.rotpixelheight; R2D_Image(sx, sy, sizex*2, sizey*2, 0, 0, 1, 1, shader); } @@ -619,7 +619,7 @@ void GLDraw_TransPicTranslate (int x, int y, int width, int height, qbyte *pic, if (gl_config.gles) return; // TODO: NOT FIXED YET - GL_Bind (translate_texture); + GL_MTBind(0, GL_TEXTURE_2D, translate_texture); c = width * height; @@ -793,11 +793,36 @@ Setup as if the screen was 320*200 */ void GL_Set2D (void) { - GL_SetShaderState2D(true); - Matrix4_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, -99999, 99999); - Matrix4_Identity(r_refdef.m_view); - r_refdef.time = realtime; + extern cvar_t gl_screenangle; + float rad, ang; + float tmp[16], tmp2[16]; + float *Matrix4_NewRotation(float a, float x, float y, float z); + float *Matrix4_NewTranslation(float x, float y, float z); + float w = vid.width, h = vid.height; + GL_SetShaderState2D(true); + + ang = (gl_screenangle.value>0?(gl_screenangle.value+45):(gl_screenangle.value-45))/90; + ang = (int)ang * 90; + if (ang) + { /*more expensive maths*/ + rad = (ang * M_PI) / 180; + + w = fabs(cos(rad)) * (vid.width) + fabs(sin(rad)) * (vid.height); + h = fabs(sin(rad)) * (vid.width) + fabs(cos(rad)) * (vid.height); + + Matrix4_Orthographic(r_refdef.m_projection, w/-2.0f, w/2.0f, h/2.0f, h/-2.0f, -99999, 99999); + + Matrix4_Identity(tmp); + Matrix4_Multiply(Matrix4_NewTranslation((vid.width/-2.0f), (vid.height/-2.0f), 0), tmp, tmp2); + Matrix4_Multiply(Matrix4_NewRotation(-ang, 0, 0, 1), tmp2, r_refdef.m_view); + } + else + { + Matrix4_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, -99999, 99999); + Matrix4_Identity(r_refdef.m_view); + } + r_refdef.time = realtime; /*flush that gl state*/ qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); @@ -1638,8 +1663,8 @@ done: if (flags&IF_CLAMP) { - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } @@ -2259,8 +2284,9 @@ void GL_Upload8 (char *name, qbyte *data, int width, int height, unsigned int fl } #endif #endif - +checkglerror(); GL_Upload32 (name, trans, width, height, flags); +checkglerror(); } void GL_Upload8FB (qbyte *data, int width, int height, unsigned flags) @@ -2425,11 +2451,11 @@ TRACE(("dbg: GL_LoadTexture: new %s\n", identifier)); glt->flags = flags; Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - - GL_Bind(glt->texnum); +checkglerror(); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8 ("8bit", data, width, height, flags, transtype); - +checkglerror(); return glt->texnum; } @@ -2466,7 +2492,7 @@ texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8FB (data, width, height, flags); @@ -2499,7 +2525,7 @@ texid_t GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *da Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Pal24 (data, palette24, width, height, flags); @@ -2531,7 +2557,7 @@ texid_t GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *da Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Pal32 (data, palette32, width, height, flags); @@ -2565,7 +2591,7 @@ texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, u Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload32 (identifier, data, width, height, flags); @@ -2599,7 +2625,7 @@ texid_t GL_LoadTexture32_BGRA (char *identifier, int width, int height, unsigned Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload32_BGRA (identifier, data, width, height, flags); @@ -2644,7 +2670,7 @@ texid_t GL_LoadCompressed(char *name) Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); if (!GL_UploadCompressed(file, &glt->width, &glt->height, (unsigned int *)&glt->flags)) return r_nulltex; @@ -2681,7 +2707,7 @@ texid_t GL_LoadTexture8Grey (char *identifier, int width, int height, unsigned c Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Grey (data, width, height, flags); @@ -2720,7 +2746,7 @@ texid_t GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned c Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_Bind(glt->texnum); + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_UploadBump (data, width, height, flags, bumpscale); diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index af9864f9..cf09a1b4 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -949,14 +949,14 @@ void Font_Free(struct font_s *f) void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py) { curfont = font; - *px = (vx*vid.pixelwidth) / (float)vid.width; - *py = (vy*vid.pixelheight) / (float)vid.height; + *px = (vx*vid.rotpixelwidth) / (float)vid.width; + *py = (vy*vid.rotpixelheight) / (float)vid.height; } void Font_BeginScaledString(struct font_s *font, float vx, float vy, float *px, float *py) { curfont = font; - *px = (vx*vid.pixelwidth) / (float)vid.width; - *py = (vy*vid.pixelheight) / (float)vid.height; + *px = (vx*vid.rotpixelwidth) / (float)vid.width; + *py = (vy*vid.rotpixelheight) / (float)vid.height; } void Font_EndString(struct font_s *font) @@ -1163,10 +1163,10 @@ int Font_DrawChar(int px, int py, unsigned int charcode) if (c->texplane >= DEFAULTPLANE) { - sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; - sw = ((curfont->charheight)*vid.width) / (float)vid.pixelwidth; - sh = ((curfont->charheight)*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight; + sw = ((curfont->charheight)*vid.width) / (float)vid.rotpixelwidth; + sh = ((curfont->charheight)*vid.height) / (float)vid.rotpixelheight; if (c->texplane == DEFAULTPLANE) v = Font_BeginChar(fontplanes.defaultfont); @@ -1175,10 +1175,10 @@ int Font_DrawChar(int px, int py, unsigned int charcode) } else { - sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; - sw = ((c->bmw)*vid.width) / (float)vid.pixelwidth; - sh = ((c->bmh)*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left)*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((py+c->top)*(int)vid.height) / (float)vid.rotpixelheight; + sw = ((c->bmw)*vid.width) / (float)vid.rotpixelwidth; + sh = ((c->bmh)*vid.height) / (float)vid.rotpixelheight; v = Font_BeginChar(fontplanes.texnum[c->texplane]); } @@ -1275,10 +1275,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch if (c->texplane >= DEFAULTPLANE) { - sx = ((px+c->left));//*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top));//*(int)vid.height) / (float)vid.pixelheight; - sw = ((curfont->charheight*cw));//*vid.width) / (float)vid.pixelwidth; - sh = ((curfont->charheight*ch));//*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left));//*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((py+c->top));//*(int)vid.height) / (float)vid.rotpixelheight; + sw = ((curfont->charheight*cw));//*vid.width) / (float)vid.rotpixelwidth; + sh = ((curfont->charheight*ch));//*vid.height) / (float)vid.rotpixelheight; if (c->texplane == DEFAULTPLANE) v = Font_BeginChar(fontplanes.defaultfont); @@ -1287,10 +1287,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch } else { - sx = ((px+c->left));//*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top));//*(int)vid.height) / (float)vid.pixelheight; - sw = ((c->bmw*cw));//*vid.width) / (float)vid.pixelwidth; - sh = ((c->bmh*ch));//*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left));//*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((py+c->top));//*(int)vid.height) / (float)vid.rotpixelheight; + sw = ((c->bmw*cw));//*vid.width) / (float)vid.rotpixelwidth; + sh = ((c->bmh*ch));//*vid.height) / (float)vid.rotpixelheight; v = Font_BeginChar(fontplanes.texnum[c->texplane]); } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index d55c6e6f..ec0c1321 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -117,7 +117,7 @@ void GL_DrawHeightmapModel (entity_t *e) else #endif { //single texture - GL_Bind(hm->textures[x+y*SECTIONS]); + GL_MTBind(0, GL_TEXTURE_2D, hm->textures[x+y*SECTIONS]); qglBegin(GL_QUADS); subsize = hm->terrainsize/hm->numsegs; minx = x*subsize; @@ -138,7 +138,7 @@ void GL_DrawHeightmapModel (entity_t *e) } qglEnd(); - GL_Bind(hm->detailtexture); + GL_MTBind(0, GL_TEXTURE_2D, hm->detailtexture); qglEnable(GL_BLEND); qglBlendFunc (GL_ZERO, GL_SRC_COLOR); diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 9379206f..c1c9e59b 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -686,7 +686,7 @@ void R_DrawHLModel(entity_t *curent) { tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w; tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h; - GL_Bind(model.texnums[skins[mesh->skinindex]]); + GL_LazyBind(0, GL_TEXTURE_2D, model.texnums[skins[mesh->skinindex]], false); } GL_Draw_HL_AliasFrame((short *) ((qbyte *) model.header + mesh->index), transformed, tex_w, tex_h); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 2cecf8c9..ea8b74f7 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -224,7 +224,7 @@ void RMod_Think (void) GetProcessAffinityMask(me, &proc, &sys); relightthreads = 0; for (i = 0; i < sizeof(proc)*8; i++) - if (proc & (1u<fromgame == fg_doom3) + D3_GenerateAreas(cl.worldmodel); + #ifdef RTLIGHTS if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) { diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 65b12329..933b4743 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -53,10 +53,8 @@ void GLBE_ClearVBO(vbo_t *vbo) if (j == 7) qglDeleteBuffersARB(1, &vboh[i]); } - if (!vbo->vbocoord) - BZ_Free(vbo->coord); - if (!vbo->vboe) - BZ_Free(vbo->indicies); + if (vbo->vertdata) + BZ_Free(vbo->vertdata); BZ_Free(vbo->meshlist); memset(vbo, 0, sizeof(*vbo)); } @@ -128,6 +126,16 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int return true; } +void *allocbuf(char **p, int elements, int elementsize) +{ + void *ret; + *p += elementsize - 1; + *p -= (unsigned int)*p & (elementsize-1); + ret = *p; + *p += elements*elementsize; + return ret; +} + void GLBE_GenBrushModelVBO(model_t *mod) { unsigned int maxvboverts; @@ -141,9 +149,8 @@ void GLBE_GenBrushModelVBO(model_t *mod) unsigned int meshes; vbo_t *vbo; - char *vboedata; mesh_t *m; - char *vbovdata; + char *p; if (!mod->numsurfaces) return; @@ -189,17 +196,18 @@ void GLBE_GenBrushModelVBO(model_t *mod) sizeof(vec3_t)+ //tdir sizeof(vec4_t); //colours - vbovdata = BZ_Malloc(maxvboverts*pervertsize); - vboedata = BZ_Malloc(maxvboelements*sizeof(index_t)); + vbo->vertdata = BZ_Malloc((maxvboverts+1)*pervertsize + (maxvboelements+1)*sizeof(index_t)); - vbo->coord = (vecV_t*)(vbovdata); - vbo->texcoord = (vec2_t*)((char*)vbo->coord+maxvboverts*sizeof(*vbo->coord)); - vbo->lmcoord = (vec2_t*)((char*)vbo->texcoord+maxvboverts*sizeof(*vbo->texcoord)); - vbo->normals = (vec3_t*)((char*)vbo->lmcoord+maxvboverts*sizeof(*vbo->lmcoord)); - vbo->svector = (vec3_t*)((char*)vbo->normals+maxvboverts*sizeof(*vbo->normals)); - vbo->tvector = (vec3_t*)((char*)vbo->svector+maxvboverts*sizeof(*vbo->svector)); - vbo->colours4f = (vec4_t*)((char*)vbo->tvector+maxvboverts*sizeof(*vbo->tvector)); - vbo->indicies = (index_t*)vboedata; + p = vbo->vertdata; + + vbo->coord = allocbuf(&p, maxvboverts, sizeof(*vbo->coord)); + vbo->texcoord = allocbuf(&p, maxvboverts, sizeof(*vbo->texcoord)); + vbo->lmcoord = allocbuf(&p, maxvboverts, sizeof(*vbo->lmcoord)); + vbo->normals = allocbuf(&p, maxvboverts, sizeof(*vbo->normals)); + vbo->svector = allocbuf(&p, maxvboverts, sizeof(*vbo->svector)); + vbo->tvector = allocbuf(&p, maxvboverts, sizeof(*vbo->tvector)); + vbo->colours4f = allocbuf(&p, maxvboverts, sizeof(*vbo->colours4f)); + vbo->indicies = allocbuf(&p, maxvboelements, sizeof(index_t)); vbo->meshcount = meshes; vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist)); @@ -265,10 +273,10 @@ void GLBE_GenBrushModelVBO(model_t *mod) vcount += v; } - if (GL_BuildVBO(vbo, vbovdata, vcount*pervertsize, vboedata, ecount*sizeof(index_t))) + if (GL_BuildVBO(vbo, vbo->coord, vcount*pervertsize, vbo->indicies, ecount*sizeof(index_t))) { - BZ_Free(vbovdata); - BZ_Free(vboedata); + BZ_Free(vbo->vertdata); + vbo->vertdata = NULL; } } /* for (i=0 ; inumsurfaces ; i++) @@ -295,7 +303,7 @@ void GLBE_UploadAllLightmaps(void) if (!lightmap[i]->modified) continue; lightmap[i]->modified = false; - GL_Bind(lightmap_textures[i]); + GL_MTBind(0, GL_TEXTURE_2D, lightmap_textures[i]); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch (lightmap_bytes) @@ -323,7 +331,7 @@ void GLBE_UploadAllLightmaps(void) lightmap[i]->deluxrectchange.t = LMBLOCK_HEIGHT; lightmap[i]->deluxrectchange.w = 0; lightmap[i]->deluxrectchange.h = 0; - GL_Bind(deluxmap_textures[i]); + GL_MTBind(0, GL_TEXTURE_2D, deluxmap_textures[i]); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexImage2D (GL_TEXTURE_2D, 0, 3 diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index bd406e71..b6991d97 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -156,6 +156,8 @@ skipwhite: } data++; c = *data; + if (c == ',' && len) + break; } while (c>32); if (len == MAX_TOKEN_CHARS) @@ -708,8 +710,9 @@ static void Shader_EntityMergable ( shader_t *shader, shaderpass_t *pass, char * shader->flags |= SHADER_ENTITY_MERGABLE; } +static void Shader_ProgAutoFields(program_t *prog); /*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/ -static void Shader_LoadPermutations(union programhandle_u *handle, char *script, int qrtype) +static void Shader_LoadPermutations(program_t *prog, char *script, int qrtype) { static char *permutationname[] = { @@ -749,7 +752,7 @@ static void Shader_LoadPermutations(union programhandle_u *handle, char *script, break; }; - memset(handle, 0, sizeof(*handle)*PERMUTATIONS); + memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS); for (p = 0; p < PERMUTATIONS; p++) { if (qrenderer != qrtype) @@ -769,16 +772,19 @@ static void Shader_LoadPermutations(union programhandle_u *handle, char *script, permutationdefines[pn++] = permutationname[n]; } permutationdefines[pn++] = NULL; - handle[p].glsl = GLSlang_CreateProgram(permutationdefines, script, script); + prog->handle[p].glsl = GLSlang_CreateProgram(permutationdefines, script, script); } #endif } + + Shader_ProgAutoFields(prog); } typedef struct sgeneric_s { struct sgeneric_s *next; char name[MAX_QPATH]; - union programhandle_u handle[PERMUTATIONS]; + qboolean failed; + program_t prog; } sgeneric_t; static sgeneric_t *sgenerics; struct sbuiltin_s @@ -1110,6 +1116,64 @@ struct sbuiltin_s "varying mediump vec2 tc;\n" "varying lowp vec3 light;\n" + "void main (void)\n" + "{\n" + " gl_FragColor = texture2D(s_t0, tc);\n" + "#ifdef UPPER\n" + " gl_FragColor.rgb += texture2D(s_t2, tc).rgb*e_uppercolour;\n" + "#endif\n" + "#ifdef LOWER\n" + " gl_FragColor.rgb += texture2D(s_t1, tc).rgb*e_lowercolour;\n" + "#endif\n" + " gl_FragColor.rgb *= light;\n" + "#ifdef FULLBRIGHT\n" + " gl_FragColor += texture2D(s_t3, tc);\n" + "#endif\n" + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "defaultskin", + "!!permu FULLBRIGHT\n" + "!!permu LOWER\n" + "!!permu UPPER\n" + //"#version 110\n" + "#ifdef VERTEX_SHADER\n" + "uniform mat4 m_modelview;\n" + "uniform mat4 m_projection;\n" + "attribute vec3 v_position;\n" + "attribute vec2 v_texcoord;\n" + "varying vec2 tc;\n" + + "attribute vec3 v_normal;\n" + "uniform vec3 e_light_dir;\n" + "uniform vec3 e_light_mul;\n" + "uniform vec3 e_light_ambient;\n" + "varying vec3 light;\n" + + "void main (void)\n" + "{\n" + " light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" + " tc = v_texcoord;\n" + " gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" /*tex_diffuse*/ + "#ifdef LOWER\n" + "uniform sampler2D s_t1;\n" /*tex_lower*/ + "uniform vec3 e_lowercolour;\n" + "#endif\n" + "#ifdef UPPER\n" + "uniform sampler2D s_t2;\n" /*tex_upper*/ + "uniform vec3 e_uppercolour;\n" + "#endif\n" + "#ifdef FULLBRIGHT\n" + "uniform sampler2D s_t3;\n" /*tex_fullbright*/ + "#endif\n" + "varying vec2 tc;\n" + "varying vec3 light;\n" + "void main (void)\n" "{\n" " gl_FragColor = texture2D(s_t0, tc);\n" @@ -1140,7 +1204,7 @@ static void Shader_FlushGenerics(void) free(g); } } -static void Shader_LoadGeneric(union programhandle_u *shader, char *name, int qrtype) +static program_t *Shader_LoadGeneric(char *name, int qrtype) { unsigned int i; void *file; @@ -1150,27 +1214,34 @@ static void Shader_LoadGeneric(union programhandle_u *shader, char *name, int qr { if (!strcmp(name, g->name)) { - memcpy(shader, g->handle, sizeof(g->handle)); - return; + if (g->failed) + return NULL; + g->prog.refs++; + return &g->prog; } } if (strlen(name) >= sizeof(g->name)) - return; /*name overflow*/ + return NULL; /*name overflow*/ g = malloc(sizeof(*g)); + memset(g, 0, sizeof(*g)); strcpy(g->name, name); g->next = sgenerics; sgenerics = g; + g->prog.refs = 1; + FS_LoadFile(name, &file); if (file) { - Shader_LoadPermutations(g->handle, file, qrtype); + Shader_LoadPermutations(&g->prog, file, qrtype); FS_FreeFile(file); + + g->prog.refs++; + return &g->prog; } else { - memset(g->handle, 0, sizeof(g->handle)); for (i = 0; *sbuiltins[i].name; i++) { if (sbuiltins[i].qrtype == qrenderer && !strcmp(sbuiltins[i].name, name)) @@ -1187,16 +1258,18 @@ static void Shader_LoadGeneric(union programhandle_u *shader, char *name, int qr continue; } #endif - Shader_LoadPermutations(g->handle, sbuiltins[i].body, sbuiltins[i].qrtype); - break; + Shader_LoadPermutations(&g->prog, sbuiltins[i].body, sbuiltins[i].qrtype); + + g->prog.refs++; + return &g->prog; } } } - - memcpy(shader, g->handle, sizeof(g->handle)); + g->failed = true; + return NULL; } -static void Shader_ProgAutoFields(shader_t *shader) +static void Shader_ProgAutoFields(program_t *prog) { unsigned int i, p; qboolean found; @@ -1233,21 +1306,21 @@ static void Shader_ProgAutoFields(shader_t *shader) {"e_light_ambient", SP_E_L_AMBIENT}, {NULL} }; - shader->numprogparams = 0; + prog->numparams = 0; #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { if (gl_config.nofixedfunc) - shader->flags |= SHADER_NOBUILTINATTR; + prog->nofixedcompat = true; for (p = 0; p < PERMUTATIONS; p++) { - if (!shader->programhandle[p].glsl) + if (!prog->handle[p].glsl) continue; - GLSlang_UseProgram(shader->programhandle[p].glsl); + GLSlang_UseProgram(prog->handle[p].glsl); for (i = 0; i < 8; i++) { - uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, va("s_t%i", i)); + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("s_t%i", i)); if (uniformloc != -1) qglUniform1iARB(uniformloc, i); } @@ -1257,24 +1330,24 @@ static void Shader_ProgAutoFields(shader_t *shader) found = false; for (p = 0; p < PERMUTATIONS; p++) { - if (!shader->programhandle[p].glsl) + if (!prog->handle[p].glsl) continue; - GLSlang_UseProgram(shader->programhandle[p].glsl); + GLSlang_UseProgram(prog->handle[p].glsl); if (u[i].ptype >= SP_FIRSTUNIFORM) - uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, u[i].name); + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, u[i].name); else - uniformloc = qglGetAttribLocationARB(shader->programhandle[p].glsl, u[i].name); + uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, u[i].name); if (uniformloc != -1) found = true; - shader->progparm[shader->numprogparams].handle[p] = uniformloc; + prog->parm[prog->numparams].handle[p] = uniformloc; } if (found) { - shader->progparm[shader->numprogparams].type = u[i].ptype; - shader->numprogparams++; + prog->parm[prog->numparams].type = u[i].ptype; + prog->numparams++; if (u[i].ptype < SP_FIRSTUNIFORM) - shader->flags |= SHADER_NOBUILTINATTR; + prog->nofixedcompat = true; } } GLSlang_UseProgram(0); @@ -1330,16 +1403,17 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p programbody[end-start] = 0; *ptr = end+1;/*skip over it all*/ - Shader_LoadPermutations(shader->programhandle, programbody, qrtype); - Shader_ProgAutoFields(shader); + shader->prog = malloc(sizeof(*shader->prog)); + memset(shader->prog, 0, sizeof(shader->prog)); + shader->prog->refs = 1; + Shader_LoadPermutations(shader->prog, programbody, qrtype); BZ_Free(programbody); } return; } - Shader_LoadGeneric(shader->programhandle, Shader_ParseString(ptr), qrtype); - Shader_ProgAutoFields(shader); + shader->prog = Shader_LoadGeneric(Shader_ParseString(ptr), qrtype); } static void Shader_GLSLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr) @@ -1444,26 +1518,30 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p int p; qboolean foundone; unsigned int uniformloc; - if (!shader->programhandle[0].glsl) + program_t *prog = shader->prog; + if (!prog) { Con_Printf("shader %s: param without program set\n", shader->name); } - else if (shader->numprogparams == SHADER_PROGPARMS_MAX) + else if (prog->numparams == SHADER_PROGPARMS_MAX) Con_Printf("shader %s: too many parms\n", shader->name); else { + if (prog->refs != 1) + Con_Printf("shader %s: parms on shared shader\n", shader->name); + foundone = false; - shader->progparm[shader->numprogparams].type = parmtype; + prog->parm[prog->numparams].type = parmtype; for (p = 0; p < PERMUTATIONS; p++) { - if (!shader->programhandle[p].glsl) + if (!prog->handle[p].glsl) continue; - GLSlang_UseProgram(shader->programhandle[p].glsl); + GLSlang_UseProgram(prog->handle[p].glsl); if (parmtype >= SP_FIRSTUNIFORM) - uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, token); + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, token); else - uniformloc = qglGetAttribLocationARB(shader->programhandle[p].glsl, token); - shader->progparm[shader->numprogparams].handle[p] = uniformloc; + uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, token); + prog->parm[prog->numparams].handle[p] = uniformloc; if (uniformloc != -1) { foundone = true; @@ -1474,17 +1552,17 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p break; case SP_TEXTURE: case SP_CONSTI: - shader->progparm[shader->numprogparams].ival = specialint; + prog->parm[prog->numparams].ival = specialint; break; case SP_CONSTF: - shader->progparm[shader->numprogparams].fval = specialfloat; + prog->parm[prog->numparams].fval = specialfloat; break; case SP_CVARF: case SP_CVARI: - shader->progparm[shader->numprogparams].pval = cv; + prog->parm[prog->numparams].pval = cv; break; case SP_CVAR3F: - shader->progparm[shader->numprogparams].pval = cv; + prog->parm[prog->numparams].pval = cv; qglUniform3fvARB(uniformloc, 1, specialvec); break; default: @@ -1495,7 +1573,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p if (!foundone && !silent) Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token); else - shader->numprogparams++; + prog->numparams++; GLSlang_UseProgram(0); } @@ -1503,6 +1581,18 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p #endif } +static void Shader_DiffuseMap(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + char *token; + token = Shader_ParseString(ptr); + shader->defaulttextures.base = R_LoadHiResTexture(token, NULL, 0); +} + +static void Shader_Translucent(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + shader->flags |= SHADER_BLEND; +} + static shaderkey_t shaderkeys[] = { {"cull", Shader_Cull}, @@ -1522,6 +1612,17 @@ static shaderkey_t shaderkeys[] = {"hlslprogram", Shader_HLSLProgramName}, //for d3d {"param", Shader_ProgramParam}, + /*doom3 compat*/ + {"diffusemap", Shader_DiffuseMap}, + {"bumpmap", NULL}, + {"specularmap", NULL}, + {"nonsolid", NULL}, + {"noimpact", NULL}, + {"translucent", Shader_Translucent}, + {"noshadows", NULL}, + {"nooverlays", NULL}, + {"nofragment", NULL}, + {NULL, NULL} }; @@ -1870,7 +1971,15 @@ static void Shaderpass_BlendFunc (shader_t *shader, shaderpass_t *pass, char **p pass->shaderbits &= ~(SBITS_BLEND_BITS); token = Shader_ParseString (ptr); - if ( !Q_stricmp (token, "blend")) + if ( !Q_stricmp (token, "diffusemap")) + { + //if the shader is translucent then this pass must be meant to be blended + if (shader->flags & SHADER_BLEND) + pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA; + else + pass->shaderbits |= SBITS_SRCBLEND_NONE | SBITS_DSTBLEND_NONE; + } + else if ( !Q_stricmp (token, "blend")) { pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA; } @@ -1891,6 +2000,8 @@ static void Shaderpass_BlendFunc (shader_t *shader, shaderpass_t *pass, char **p pass->shaderbits |= Shader_BlendFactor(token, false); token = Shader_ParseString (ptr); + if (*token == ',') + token = Shader_ParseString (ptr); pass->shaderbits |= Shader_BlendFactor(token, true); } } @@ -2010,28 +2121,31 @@ static void Shaderpass_Scale ( shader_t *shader, shaderpass_t *pass, char **ptr tcmod = &pass->tcmods[pass->numtcmods]; - token = Shader_ParseString ( ptr ); - if (!strcmp(token, "static")) - { - tcmod->type = SHADER_TCMOD_SCALE; - tcmod->args[0] = Shader_ParseFloat ( ptr ); - } - else - { - Con_Printf("Bad shader scale\n"); - return; - } + tcmod->type = SHADER_TCMOD_SCALE; + + token = Shader_ParseString ( ptr ); + if (!strcmp(token, "static")) + { + tcmod->args[0] = Shader_ParseFloat ( ptr ); + } + else + { + tcmod->args[0] = atof(token); + } + + while (**ptr == ' ' || **ptr == '\t') + *ptr+=1; + if (**ptr == ',') + *ptr+=1; token = Shader_ParseString ( ptr ); if (!strcmp(token, "static")) { - tcmod->type = SHADER_TCMOD_SCALE; tcmod->args[1] = Shader_ParseFloat ( ptr ); } else { - Con_Printf("Bad shader scale\n"); - return; + tcmod->args[1] = atof(token); } pass->numtcmods++; @@ -2115,28 +2229,103 @@ static void Shaderpass_NoLightMap ( shader_t *shader, shaderpass_t *pass, char * pass->rgbgen = RGB_GEN_IDENTITY; } +static void Shaderpass_MaskColor(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + pass->shaderbits |= SBITS_MASK_RED|SBITS_MASK_GREEN|SBITS_MASK_BLUE; +} +static void Shaderpass_MaskRed(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + pass->shaderbits |= SBITS_MASK_RED; +} +static void Shaderpass_MaskGreen(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + pass->shaderbits |= SBITS_MASK_GREEN; +} +static void Shaderpass_MaskBlue(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + pass->shaderbits |= SBITS_MASK_BLUE; +} +static void Shaderpass_MaskAlpha(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + pass->shaderbits |= SBITS_MASK_ALPHA; +} +static void Shaderpass_AlphaTest(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + if (Shader_ParseFloat(ptr) == 0.5) + pass->shaderbits |= SBITS_ATEST_GE128; + else + Con_Printf("unsupported alphatest value\n"); +} +static void Shaderpass_TexGen(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + char *token = Shader_ParseString(ptr); + if (!strcmp(token, "normal")) + pass->tcgen = TC_GEN_NORMAL; + else if (!strcmp(token, "skybox")) + pass->tcgen = TC_GEN_SKYBOX; + else if (!strcmp(token, "wobblesky")) + { + pass->tcgen = TC_GEN_WOBBLESKY; + token = Shader_ParseString(ptr); + token = Shader_ParseString(ptr); + token = Shader_ParseString(ptr); + } + else if (!strcmp(token, "reflect")) + pass->tcgen = TC_GEN_REFLECT; + else + { + Con_Printf("texgen token not understood\n"); + } +} +static void Shaderpass_CubeMap(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + char *token = Shader_ParseString(ptr); + int flags = Shader_SetImageFlags(shader); + if (pass->tcgen == TC_GEN_BASE) + pass->tcgen = TC_GEN_SKYBOX; + pass->texgen = T_GEN_SKYBOX; + pass->anim_frames[0] = r_nulltex;//Shader_FindImage(token, flags); + + if (!TEXVALID(pass->anim_frames[0])) + { + pass->texgen = T_GEN_SINGLEMAP; + pass->anim_frames[0] = missing_texture; + } +} + static shaderkey_t shaderpasskeys[] = { - {"rgbgen", Shaderpass_RGBGen }, - {"blendfunc", Shaderpass_BlendFunc }, - {"depthfunc", Shaderpass_DepthFunc }, - {"depthwrite", Shaderpass_DepthWrite }, - {"alphafunc", Shaderpass_AlphaFunc }, - {"tcmod", Shaderpass_TcMod }, - {"map", Shaderpass_Map }, - {"animmap", Shaderpass_AnimMap }, - {"clampmap", Shaderpass_ClampMap }, - {"videomap", Shaderpass_VideoMap }, - {"tcgen", Shaderpass_TcGen }, - {"envmap", Shaderpass_EnvMap },//for alienarena - {"nolightmap", Shaderpass_NoLightMap },//for alienarena - {"scale", Shaderpass_Scale },//for alienarena - {"scroll", Shaderpass_Scroll },//for alienarena - {"alphagen", Shaderpass_AlphaGen }, - {"alphashift", Shaderpass_AlphaShift },//for alienarena - {"alphamask", Shaderpass_AlphaMask },//for alienarena - {"detail", Shaderpass_Detail }, - {NULL, NULL } + {"rgbgen", Shaderpass_RGBGen}, + {"blendfunc", Shaderpass_BlendFunc}, + {"depthfunc", Shaderpass_DepthFunc}, + {"depthwrite", Shaderpass_DepthWrite}, + {"alphafunc", Shaderpass_AlphaFunc}, + {"tcmod", Shaderpass_TcMod}, + {"map", Shaderpass_Map}, + {"animmap", Shaderpass_AnimMap}, + {"clampmap", Shaderpass_ClampMap}, + {"videomap", Shaderpass_VideoMap}, + {"tcgen", Shaderpass_TcGen}, + {"envmap", Shaderpass_EnvMap},//for alienarena + {"nolightmap", Shaderpass_NoLightMap},//for alienarena + {"scale", Shaderpass_Scale},//for alienarena + {"scroll", Shaderpass_Scroll},//for alienarena + {"alphagen", Shaderpass_AlphaGen}, + {"alphashift", Shaderpass_AlphaShift},//for alienarena + {"alphamask", Shaderpass_AlphaMask},//for alienarena + {"detail", Shaderpass_Detail}, + + /*doom3 compat*/ + {"blend", Shaderpass_BlendFunc}, + {"maskcolor", Shaderpass_MaskColor}, + {"maskred", Shaderpass_MaskRed}, + {"maskgreen", Shaderpass_MaskGreen}, + {"maskblue", Shaderpass_MaskBlue}, + {"maskalpha", Shaderpass_MaskAlpha}, + {"alphatest", Shaderpass_AlphaTest}, + {"texgen", Shaderpass_TexGen}, + {"cameracubemap",Shaderpass_CubeMap}, + {NULL, NULL} }; // =============================================================== @@ -2297,18 +2486,22 @@ void Shader_Free (shader_t *shader) Hash_RemoveData(&shader_active_hash, shader->name, shader); #ifdef GLQUAKE - if (qrenderer == QR_OPENGL) + if (qrenderer == QR_OPENGL && shader->prog) { + program_t *prog = shader->prog; int p; - for (p = 0; p < PERMUTATIONS; p++) + if (--prog->refs == 0) { - if (shader->programhandle[p].glsl) - qglDeleteProgramObject_(shader->programhandle[p].glsl); + for (p = 0; p < PERMUTATIONS; p++) + { + if (prog->handle[p].glsl) + qglDeleteProgramObject_(prog->handle[p].glsl); + } + free(prog); } + shader->prog = NULL; } #endif - memset(&shader->programhandle, 0, sizeof(shader->programhandle)); - if (shader->skydome) { Z_Free (shader->skydome); @@ -2568,6 +2761,9 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2) if ((pass->shaderbits & SBITS_ATEST_BITS) && (!(pass2->shaderbits & SBITS_MISC_DEPTHEQUALONLY) || pass2->texgen != T_GEN_LIGHTMAP)) return; + if ((pass->shaderbits & SBITS_MASK_BITS) != (pass2->shaderbits & SBITS_MASK_BITS)) + return; + // check if we can use multiple passes if (pass2->blendmode == GL_DOT3_RGB_ARB) { @@ -2714,18 +2910,24 @@ void Shader_Finish (shader_t *s) pass = &s->passes[s->numpasses++]; pass = &s->passes[0]; pass->tcgen = TC_GEN_BASE; - pass->anim_frames[0] = R_LoadHiResTexture(s->name, NULL, IF_NOALPHA); - if (!TEXVALID(pass->anim_frames[0])) + if (TEXVALID(s->defaulttextures.base)) + pass->texgen = T_GEN_DIFFUSE; + else { - Con_Printf("Shader %s failed to load default texture\n", s->name); - pass->anim_frames[0] = missing_texture; + pass->texgen = T_GEN_SINGLEMAP; + pass->anim_frames[0] = R_LoadHiResTexture(s->name, NULL, IF_NOALPHA); + if (!TEXVALID(pass->anim_frames[0])) + { + Con_Printf("Shader %s failed to load default texture\n", s->name); + pass->anim_frames[0] = missing_texture; + } + Con_Printf("Shader %s with no passes and no surfaceparm nodraw, inserting pass\n", s->name); } pass->shaderbits |= SBITS_MISC_DEPTHWRITE; pass->rgbgen = RGB_GEN_VERTEX; pass->alphagen = ALPHA_GEN_IDENTITY; pass->numMergedPasses = 1; Shader_SetBlendmode(pass); - Con_Printf("Shader %s with no passes and no surfaceparm nodraw, inserting pass\n", s->name); } if (!Q_stricmp (s->name, "flareShader")) @@ -2749,7 +2951,7 @@ void Shader_Finish (shader_t *s) s->sort = SHADER_SORT_DECAL; } - if (r_vertexlight.value && !s->programhandle[0].glsl) + if (r_vertexlight.value && !s->prog) { // do we have a lightmap pass? pass = s->passes; @@ -2836,7 +3038,7 @@ done:; pass = s->passes; for (i = 0; i < s->numpasses; i++, pass++) { - if (!(pass->shaderbits & SBITS_BLEND_BITS)) + if (!(pass->shaderbits & (SBITS_BLEND_BITS|SBITS_MASK_BITS))) { break; } @@ -2933,7 +3135,7 @@ done:; s->flags &= ~SHADER_DEPTHWRITE; } - if (s->programhandle[0].glsl) + if (s->prog) { if (!s->numpasses) s->numpasses = 1; @@ -3293,23 +3495,14 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "{\n" "sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/ "program defaultwarp\n" - "if r_wateralpha != 1\n" - "[\n" - "param cvarf r_wateralpha wateralpha\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0 0 3 0.1\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0 0 3 0.1\n" + "if r_wateralpha != 1\n" + "[\n" "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" - "}\n" - "]\n" - "if r_wateralpha == 1\n" - "[\n" - "param constf 1 wateralpha\n" - "{\n" - "map $diffuse\n" - "tcmod turb 0 0 3 0.1\n" - "}\n" - "]\n" + "]\n" + "}\n" "surfaceparm nodlight\n" "}\n" ); @@ -3808,9 +4001,16 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena if (defaultgen) { - memset ( s, 0, sizeof( shader_t ) ); - defaultgen(shortname, s, genargs); - Com_sprintf ( s->name, MAX_QPATH, shortname ); + memset(s, 0, sizeof(shader_t)); + Com_sprintf(s->name, MAX_QPATH, shortname); + if (!strcmp(shortname, "textures/common/clip")) + Shader_DefaultScript(shortname, s, + "{\n" + "surfaceparm nodraw\n" + "surfaceparm nodlight\n" + "}\n"); + else + defaultgen(shortname, s, genargs); Hash_Add(&shader_active_hash, s->name, s, &s->bucket); s->generator = defaultgen; s->genargs = genargs; @@ -3833,6 +4033,7 @@ void Shader_DoReload(void) { Con_Printf ( "Initializing Shaders.\n" ); + COM_EnumerateFiles("materials/*.mtr", Shader_InitCallback, NULL); COM_EnumerateFiles("shaders/*.shader", Shader_InitCallback, NULL); COM_EnumerateFiles("scripts/*.shader", Shader_InitCallback, NULL); //COM_EnumerateFiles("scripts/*.rscript", Shader_InitCallback, NULL); diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index ff184bfc..d3fc2f7d 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1178,7 +1178,6 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) Matrix4_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); v2[0]*=r_view_width; v2[1]*=r_view_height; -// GL_TransformToScreen(v, v2); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); x = v2[0]; y = v2[1]; @@ -1195,7 +1194,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) y1 = y2 = y; } } -#if 0 +#if 1 // this code doesn't handle boxes with any points behind view properly x1 = 1000;x2 = -1000; y1 = 1000;y2 = -1000; @@ -1205,7 +1204,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = (i & 2) ? mins[1] : maxs[1]; v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; - GL_TransformToScreen(v, v2); + Matrix4_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); v2[0]*=r_view_width; v2[1]*=r_view_height; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); @@ -1266,7 +1265,7 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) } else { - GL_Bind(depthtexture); + GL_MTBind(0, GL_TEXTURE_2D, depthtexture); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); } } @@ -1386,7 +1385,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) { l->stexture = GL_AllocNewTexture(smsize, smsize); - GL_Bind(l->stexture); + GL_MTBind(0, GL_TEXTURE_2D, l->stexture); qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); // qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1537,7 +1536,8 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) bench.numlights++; qglMatrixMode(GL_TEXTURE); - GL_MBind(7, l->stexture); + GL_MTBind(7, GL_TEXTURE_2D, l->stexture); + // qglEnable(GL_TEXTURE_2D); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); @@ -1642,7 +1642,6 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) GL_SelectVBO(0); GL_SelectEBO(0); qglEnableClientState(GL_VERTEX_ARRAY); - qglEnable(GL_VERTEX_ARRAY); BE_PushOffsetShadow(true); @@ -1741,7 +1740,6 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q GL_SelectVBO(0); GL_SelectEBO(0); qglEnableClientState(GL_VERTEX_ARRAY); - qglEnable(GL_VERTEX_ARRAY); //draw cached world shadow mesh qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), sm->verts); qglDrawRangeElements(GL_TRIANGLES, 0, sm->numverts, sm->numindicies, GL_INDEX_TYPE, sm->indicies); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 57b0187f..046a3692 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -636,7 +636,7 @@ static void GL_DrawSkyGrid (texture_t *tex) float time = cl.gametime+realtime-cl.gametimemark; PPL_RevertToKnownState(); - GL_Bind (tex->shader->defaulttextures.base); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.base, false); speedscale = time*8; speedscale -= (int)speedscale & ~127; @@ -649,7 +649,7 @@ static void GL_DrawSkyGrid (texture_t *tex) } qglEnable (GL_BLEND); - GL_Bind (tex->shader->defaulttextures.fullbright); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.fullbright, false); speedscale = time*16; speedscale -= (int)speedscale & ~127; diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 2a685af7..1140a899 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -243,11 +243,10 @@ qboolean R_CullSphere (vec3_t origin, float radius); #ifdef GLQUAKE void R_TranslatePlayerSkin (int playernum); -void GL_Bind (texid_t texnum); -void GL_MBind(int tmunum, texid_t texnum); +void GL_MTBind(int tmu, int target, texid_t texnum); /*use this if you're going to change the texture object*/ +void GL_LazyBind(int tmu, int target, texid_t texnum, qboolean arrays); /*use this if you don't care about the object itself, only that it is bound*/ void GL_CullFace(unsigned int sflags); void GL_TexEnv(GLenum mode); -void GL_BindType (int type, texid_t texnum); void GL_FlushBackEnd (void); // Multitexture @@ -355,6 +354,9 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer); #ifdef MAP_DOOM void GLR_DoomWorld(); #endif +qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf); +unsigned char *D3_CalcVis(model_t *mod, vec3_t org); +void D3_GenerateAreas(model_t *mod); //gl_bloom.c #ifdef GLQUAKE diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 73eef101..d60ba415 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -122,12 +122,15 @@ enum SBITS_MISC_DEPTHWRITE = 0x00001000, SBITS_MISC_NODEPTHTEST = 0x00002000, - SBITS_MISC_DEPTHEQUALONLY = 0x00004000, SBITS_MISC_DEPTHCLOSERONLY = 0x00008000, - -// SBITS_MISC_POLYFILL_LINES = 0x00008000, #define SBITS_MISC_BITS 0x0000f000 + + SBITS_MASK_RED = 0x00010000, + SBITS_MASK_GREEN = 0x00020000, + SBITS_MASK_BLUE = 0x00040000, + SBITS_MASK_ALPHA = 0x00080000, +#define SBITS_MASK_BITS 0x000f0000 }; @@ -176,11 +179,15 @@ typedef struct shaderpass_s { TC_GEN_ENVIRONMENT, TC_GEN_DOTPRODUCT, TC_GEN_VECTOR, + TC_GEN_FOG, - //these are really for use only in glsl stuff. + //these are really for use only in glsl stuff or perhaps cubemaps, as they generate 3d coords. TC_GEN_NORMAL, TC_GEN_SVECTOR, TC_GEN_TVECTOR, + TC_GEN_SKYBOX, + TC_GEN_WOBBLESKY, + TC_GEN_REFLECT, } tcgen; int numtcmods; tcmod_t tcmods[SHADER_MAX_TC_MODS]; @@ -207,6 +214,7 @@ typedef struct shaderpass_s { T_GEN_CURRENTRENDER,//copy the current screen to a texture, and draw that T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible + T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP } texgen; enum { @@ -300,6 +308,16 @@ union programhandle_u { int glsl; }; + +typedef struct programshared_s +{ + int refs; + qboolean nofixedcompat; + union programhandle_u handle[PERMUTATIONS]; + int numparams; + shaderprogparm_t parm[SHADER_PROGPARMS_MAX]; +} program_t; + typedef struct { float factor; float unit; @@ -344,12 +362,9 @@ struct shader_s SHADER_NODLIGHT = 1 << 15, //from surfaceflags SHADER_HASLIGHTMAP = 1 << 16, SHADER_HASTOPBOTTOM = 1 << 17, - SHADER_NOBUILTINATTR = 1 << 18 /*using custom glsl attributes so don't feed it builtins*/ } flags; - union programhandle_u programhandle[PERMUTATIONS]; - int numprogparams; - shaderprogparm_t progparm[SHADER_PROGPARMS_MAX]; + program_t *prog; shaderpass_t passes[SHADER_PASS_MAX]; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 8a3b467a..e0649d1b 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1164,6 +1164,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) pbool init; char keyname[256]; int n; + int nest = 1; // eval_t *val; @@ -1179,12 +1180,20 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) // parse key data = QCC_COM_Parse (data); if (qcc_token[0] == '}') + { + if (--nest) + continue; break; + } + if (qcc_token[0] == '{' && !qcc_token[1]) + nest++; if (!data) { printf ("ED_ParseEntity: EOF without closing brace\n"); return NULL; } + if (nest > 1) + continue; strncpy (keyname, qcc_token, sizeof(keyname)-1); keyname[sizeof(keyname)-1] = 0; @@ -1714,6 +1723,11 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) file = QCC_COM_Parse(file); if (file == NULL) break; //finished reading file + else if (!strcmp(qcc_token, "Version")) + { + file = QCC_COM_Parse(file); + //qcc_token is a version number + } else if (!strcmp(qcc_token, "entity")) { if (entsize == 0 && resethunk) //edicts have not yet been initialized, and this is a compleate load (memsize has been set) diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 2287813e..072d58d1 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -536,8 +536,12 @@ void SV_Map_f (void) snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level); if (!COM_FCheckExists (expanded)) { - Con_TPrintf (STL_CANTFINDMAP, expanded); - return; + snprintf (expanded, sizeof(expanded), "maps/%s.cm", level); + if (!COM_FCheckExists (expanded)) + { + Con_TPrintf (STL_CANTFINDMAP, expanded); + return; + } } } } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index fce5f9bd..72396cef 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -846,6 +846,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us { strcpy (sv.name, server); sprintf (sv.modelname,"maps/%s.bsp", server); + if (!COM_FCheckExists(sv.modelname)) + if (COM_FCheckExists(va("maps/%s.cm", server))) + sprintf (sv.modelname,"maps/%s.cm", server); } sv.state = ss_loading; sv.world.worldmodel = Mod_ForName (sv.modelname, true);