diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 1c593bbe1..840c2e8c8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -2667,7 +2667,7 @@ void CLQ1_AddShadow(entity_t *ent) "alphagen vertex\n" "}\n" "}\n"); - TEXASSIGN(s->defaulttextures.base, balltexture); + TEXASSIGN(s->defaulttextures->base, balltexture); tx = ent->model->maxs[0] - ent->model->mins[0]; ty = ent->model->maxs[1] - ent->model->mins[1]; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index af3d3fe8c..9e1d341aa 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -288,20 +288,23 @@ void CL_UpdateWindowTitle(void) { if (VID_SetWindowCaption) { + char title[2048]; switch (cls.state) { default: #ifndef CLIENTONLY if (sv.state) - VID_SetWindowCaption(va("%s: %s", fs_gamename.string, sv.name)); + Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, sv.name); else #endif - VID_SetWindowCaption(va("%s: %s", fs_gamename.string, cls.servername)); + Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, cls.servername); break; case ca_disconnected: - VID_SetWindowCaption(va("%s: disconnected", fs_gamename.string)); + Q_snprintfz(title, sizeof(title), "%s: disconnected", fs_gamename.string); break; } + + VID_SetWindowCaption(title); } } diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index f11729aa3..e1192e5b5 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -111,16 +111,18 @@ typedef struct serverinfo_s char name[64]; //hostname. netadr_t adr; + short special; //flags + short protocol; + unsigned char players; unsigned char maxplayers; - qbyte special; //flags qbyte sends; qbyte insortedlist; qbyte numhumans; qbyte numbots; qbyte freeslots; - qbyte protocol; + qbyte pad; char modname[8+1]; char qcstatus[8+1]; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 37c82ee90..fef912a89 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1094,6 +1094,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) #define endstage() if (!cls.timedemo && giveuptimeframerate = 100; // smoother fading } -static qbyte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8}; +static struct{ + qbyte colour; + char *name; +} q2splash_info[] = +{ + {0x00, "q2part.te_splashunknown"}, + {0xe0, "q2part.te_splashsparks"}, + {0xb0, "q2part.te_splashbluewater"}, + {0x50, "q2part.te_splashbrownwater"}, + {0xd0, "q2part.te_splashslime"}, + {0xe0, "q2part.te_splashlava"}, + {0xe8, "q2part.te_splashblood"} +}; #define ATTN_NONE 0 #define ATTN_NORM 1 @@ -2632,16 +2644,10 @@ fixme: MSG_ReadPos (pos); MSG_ReadDir (dir); r = MSG_ReadByte (); - if (r > 6) - color = 0x00; - else - color = splash_color[r]; - P_RunParticleEffect (pos, dir, color, cnt); - - if (r == Q2SPLASH_BLUE_WATER || r == Q2SPLASH_BROWN_WATER) - { - P_RunParticleEffectTypeString(pos, dir, 1, "te_watersplash"); - } + if (r > sizeof(q2splash_info)/sizeof(q2splash_info[0])) + r = 0; + if (P_RunParticleEffectTypeString(pos, dir, cnt, q2splash_info[r].name)) + P_RunParticleEffect (pos, dir, q2splash_info[r].colour, cnt); if (r == Q2SPLASH_SPARKS) { r = rand() & 3; @@ -2651,13 +2657,6 @@ fixme: Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/spark6.wav"), 1, ATTN_NORM, 0); else Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/spark7.wav"), 1, ATTN_NORM, 0); - -// if (r == 0) -// Q2S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0); -// else if (r == 1) -// Q2S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0); -// else -// Q2S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0); } break; diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 1895bbffa..d2c6ac0aa 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1941,7 +1941,11 @@ void CLQ2_AddEntities (void) if (cls.state != ca_active) return; - if (cl.time*1000 > cl.q2frame.servertime) + cl.lerpfrac = 1.0 - (cl.q2frame.servertime - cl.time*1000) * 0.01; +// Con_Printf("%g: %g\n", cl.q2frame.servertime - (cl.time*1000), cl.lerpfrac); + cl.lerpfrac = bound(0, cl.lerpfrac, 1); + +/* if (cl.time*1000 > cl.q2frame.servertime) { // if (cl_showclamp.value) // Con_Printf ("high clamp %f\n", cl.time - cl.q2frame.servertime); @@ -1957,7 +1961,7 @@ void CLQ2_AddEntities (void) } else cl.lerpfrac = 1.0 - (cl.q2frame.servertime - cl.time*1000) * 0.01; - +*/ CLQ2_CalcViewValues (); CLQ2_AddPacketEntities (&cl.q2frame); #if 0 diff --git a/engine/client/image.c b/engine/client/image.c index c584ff098..6e54f834d 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -3688,18 +3688,22 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag case PTI_S3RGBA1: //mostly compatible, but I don't want to push it. case PTI_S3RGBA3: case PTI_S3RGBA5: + case PTI_WHOLEFILE: //erk. meh. break; + case PTI_R8: + case PTI_RG8: case PTI_RGB565: case PTI_RGBX8: case PTI_BGRX8: case PTI_S3RGB1: - break; + break; //already no alpha in these formats case PTI_DEPTH16: case PTI_DEPTH24: case PTI_DEPTH32: case PTI_DEPTH24_8: break; + case PTI_MAX: break; //stfu } //FIXME: fill alpha channel with 255? } @@ -4305,7 +4309,7 @@ image_t *Image_GetTexture(const char *identifier, const char *subpath, unsigned qboolean dontposttoworker = (flags & (IF_NOWORKER | IF_LOADNOW)); qboolean lowpri = (flags & IF_LOWPRIORITY); - qboolean highpri = (flags & IF_HIGHPRIORITY); +// qboolean highpri = (flags & IF_HIGHPRIORITY); flags &= ~(IF_LOADNOW | IF_LOWPRIORITY | IF_HIGHPRIORITY); #ifdef LOADERTHREAD diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 310cf36c2..7fcd35665 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -91,7 +91,7 @@ static qboolean restore_spi; static int originalmouseparms[3], newmouseparms[3] = {0, 0, 0}; qboolean mouseinitialized; static qboolean mouseparmsvalid, mouseactivatetoggle; -static qboolean mouseshowtoggle = 1; +qboolean mouseshowtoggle = 1; static qboolean dinput_acquired; unsigned int uiWheelMessage; @@ -2192,7 +2192,7 @@ void INS_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdev if (!in_nonstandarddeadkeys.ival) { for (unicode = 0; unicode < chars-1; unicode++) - Key_Event (qdeviceid, 0, wchars[unicode], down); + IN_KeyEvent(qdeviceid, down, 0, wchars[unicode]); } unicode = wchars[chars-1]; } @@ -2204,6 +2204,6 @@ void INS_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdev if (shift_down && unicode < K_MAX && keyshift[unicode]) unicode = keyshift[unicode]; } - Key_Event (qdeviceid, qcode, unicode, down); + IN_KeyEvent(qdeviceid, down, qcode, unicode); } #endif diff --git a/engine/client/keys.c b/engine/client/keys.c index b13c557f2..9110bd397 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -2126,13 +2126,13 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down) { Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_cwindows); - if (!cls.state && !Key_Dest_Has(~kdm_game)) + if (!cls.state && !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) M_ToggleMenu_f (); } else if (Key_Dest_Has(kdm_cwindows)) { Key_Dest_Remove(kdm_cwindows); - if (!cls.state && !Key_Dest_Has(~kdm_game)) + if (!cls.state && !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) M_ToggleMenu_f (); } #ifdef TEXTEDITOR diff --git a/engine/client/m_items.c b/engine/client/m_items.c index e0be67c63..725c1fab1 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -116,7 +116,7 @@ void Draw_Hexen2BigFontString(int x, int y, const char *text) "}\n" "sort additive\n" "}\n"); - if (!p->defaulttextures.base) + if (!p->defaulttextures->base) { void *file; qofs_t fsize = FS_LoadFile("gfx/menu/bigfont.lmp", &file); @@ -125,11 +125,11 @@ void Draw_Hexen2BigFontString(int x, int y, const char *text) unsigned int w = ((unsigned int*)file)[0]; unsigned int h = ((unsigned int*)file)[1]; if (8+w*h==fsize) - p->defaulttextures.base = R_LoadReplacementTexture("gfx/menu/bigfont.lmp", NULL, IF_NOPCX|IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP, (qbyte*)file+8, w, h, TF_H2_TRANS8_0); + p->defaulttextures->base = R_LoadReplacementTexture("gfx/menu/bigfont.lmp", NULL, IF_NOPCX|IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP, (qbyte*)file+8, w, h, TF_H2_TRANS8_0); FS_FreeFile(file); //got image data } - if (!p->defaulttextures.base) - p->defaulttextures.base = R_LoadHiResTexture("gfx/menu/bigfont.lmp", NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP); + if (!p->defaulttextures->base) + p->defaulttextures->base = R_LoadHiResTexture("gfx/menu/bigfont.lmp", NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP); } while(*text) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 43a5e4ffb..04c2757a5 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -680,6 +680,7 @@ const char *presetexec[] = "seta gl_polyblend 0;" "seta gl_flashblend 0;" "seta gl_specular 0;" + "seta r_deluxemapping 0;" "seta r_loadlit 0;" "seta r_fastsky 1;" "seta r_drawflame 0;" @@ -779,10 +780,12 @@ const char *presetexec[] = "r_shadow_realtime_dlight 1;" // "gl_detail 1;" "r_lightstylesmooth 1;" + "r_deluxemapping 1;" "gl_texture_anisotropic_filtering 4;" , // realtime options "r_bloom 1;" + "r_deluxemapping 0;" //won't be seen anyway "r_particledesc \"high tsshaft\";" "r_waterstyle 3;" "r_glsl_offsetmapping 1;" diff --git a/engine/client/m_single.c b/engine/client/m_single.c index ea503f9c0..52c2aed0b 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -87,7 +87,7 @@ static void M_Menu_LoadSave_Remove(menu_t *menu) loadsavemenuinfo_t *info = menu->data; if (info->picshader) { - Image_UnloadTexture(info->picshader->defaulttextures.base); + Image_UnloadTexture(info->picshader->defaulttextures->base); R_UnloadShader(info->picshader); } } @@ -107,7 +107,7 @@ static void M_Menu_LoadSave_Preview_Draw(int x, int y, menucustom_t *item, menu_ info->picslot = slot; if (info->picshader) { - Image_UnloadTexture(info->picshader->defaulttextures.base); + Image_UnloadTexture(info->picshader->defaulttextures->base); R_UnloadShader(info->picshader); } info->picshader = R_RegisterPic(va("saves/s%i/screeny.tga", slot)); diff --git a/engine/client/merged.h b/engine/client/merged.h index e07b26c60..98ea4df8f 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -355,6 +355,7 @@ typedef struct } srect_t; typedef struct texnums_s { + char mapname[MAX_QPATH]; //the 'official' name of the diffusemap. used to generate filenames for other textures. texid_t base; //regular diffuse texture. may have alpha if surface is transparent texid_t bump; //normalmap. height values packed in alpha. texid_t specular; //specular lighting values. @@ -362,6 +363,8 @@ typedef struct texnums_s { texid_t loweroverlay; //diffuse texture for the lower body(trouser colour). no alpha channel. added to base.rgb texid_t paletted; //8bit paletted data, just because. texid_t fullbright; + texid_t reflectcube; + texid_t reflectmask; } texnums_t; //not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented) @@ -414,7 +417,7 @@ typedef struct rendererinfo_s { /*Draws an entire mesh list from a VBO. vbo can be null, in which case the chain may be drawn without batching. Rules for using a list: Every mesh must be part of the same VBO, shader, lightmap, and must have the same pointers set*/ void (*BE_DrawMesh_List)(shader_t *shader, int nummeshes, struct mesh_s **mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags); - void (*BE_DrawMesh_Single)(shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags); + void (*BE_DrawMesh_Single)(shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, unsigned int be_flags); void (*BE_SubmitBatch)(struct batch_s *batch); struct batch_s *(*BE_GetTempBatch)(void); //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required diff --git a/engine/client/net_master.c b/engine/client/net_master.c index c21158fe4..ec049dcc5 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -762,13 +762,21 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b) case SLKEY_TOOMANY: break; - // warning: enumeration value ‘SLKEY_*’ not handled in switch + case SLKEY_ISPROXY: + return Master_CompareInteger(a->special & SS_PROXY, b->special & SS_PROXY, SLIST_TEST_LESS); + case SLKEY_ISLOCAL: + return Master_CompareInteger(a->special & SS_LOCAL, b->special & SS_LOCAL, SLIST_TEST_LESS); + case SLKEY_ISFAVORITE: + return Master_CompareInteger(a->special & SS_FAVORITE, b->special & SS_FAVORITE, SLIST_TEST_LESS); + case SLKEY_MOD: case SLKEY_PROTOCOL: case SLKEY_NUMBOTS: case SLKEY_NUMHUMANS: case SLKEY_QCSTATUS: - case SLKEY_ISFAVORITE: + case SLKEY_SERVERINFO: + case SLKEY_PLAYER0: + default: break; } diff --git a/engine/client/p_script.c b/engine/client/p_script.c index e604536ed..c05eb8775 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -3620,7 +3620,7 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3] { vec3_t morg, mdir; PScript_ApplyOrgVel(morg, mdir, org, axis[0], i, count, ptype); - CL_SpawnSpriteEffect(morg, mdir, (mod->rflags&RF_USEORIENTATION)?axis[0]:NULL, mod->model, mod->framestart, (mod->frameend?mod->frameend:(mod->model->numframes - mod->framestart)), mod->framerate?mod->framerate:10, mod->alpha?mod->alpha:1, ptype->rotationmin*180/M_PI, ptype->gravity, mod->traileffect, mod->rflags & ~RF_USEORIENTATION); + CL_SpawnSpriteEffect(morg, mdir, (mod->rflags&RF_USEORIENTATION)?axis[2]:NULL, mod->model, mod->framestart, (mod->frameend?mod->frameend:(mod->model->numframes - mod->framestart)), mod->framerate?mod->framerate:10, mod->alpha?mod->alpha:1, ptype->rotationmin*180/M_PI, ptype->gravity, mod->traileffect, mod->rflags & ~RF_USEORIENTATION); } } } @@ -5110,7 +5110,7 @@ static void GL_DrawTexturedParticle(int count, particle_t **plist, plooks_t *typ if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } @@ -5168,7 +5168,7 @@ static void GL_DrawTexturedParticle(int count, particle_t **plist, plooks_t *typ if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } } @@ -5186,7 +5186,7 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) if (pscripttmesh.numvertexes >= BUFFERVERTS-3) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, 0); pscripttmesh.numvertexes = 0; } @@ -5222,7 +5222,7 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) if (pscripttmesh.numvertexes) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, 0); pscripttmesh.numvertexes = 0; } } @@ -5402,7 +5402,7 @@ static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } @@ -5448,7 +5448,7 @@ static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } } @@ -5470,7 +5470,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } @@ -5514,7 +5514,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures, 0); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, 0); pscriptmesh.numvertexes = 0; } } diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index cfee732fc..733622050 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1281,7 +1281,7 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g cl_numstrisvert = csqc_poly_startvert; cl_numstrisidx = csqc_poly_startidx; - BE_DrawMesh_Single(csqc_poly_shader, &mesh, NULL, &csqc_poly_shader->defaulttextures, 0); + BE_DrawMesh_Single(csqc_poly_shader, &mesh, NULL, 0); } else { diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 96dcc7e88..fb30906e2 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -781,7 +781,7 @@ void QCBUILTIN PF_CL_drawline (pubprogfuncs_t *prinst, struct globalvars_s *pr_g "}\n" "}\n"); - BE_DrawMesh_Single(shader_draw_line, &mesh, NULL, &shader_draw_line->defaulttextures, flags|BEF_LINES); + BE_DrawMesh_Single(shader_draw_line, &mesh, NULL, flags|BEF_LINES); } //vector drawgetimagesize(string pic) = #460; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 0fef1a150..cc1555473 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -147,7 +147,7 @@ void R2D_Init(void) int i; unsigned int glossval; unsigned int normval; - extern cvar_t gl_specular_fallback, gl_specular_fallbackexp; + extern cvar_t gl_specular_fallback, gl_specular_fallbackexp, gl_texturemode; conback = NULL; Shader_Init(); @@ -198,13 +198,13 @@ void R2D_Init(void) "map $diffuse\n" "}\n" "}\n"); - TEXDOWAIT(draw_backtile->defaulttextures.base); - if (!TEXLOADED(draw_backtile->defaulttextures.base)) - draw_backtile->defaulttextures.base = R_LoadHiResTexture("gfx/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); - if (!TEXLOADED(draw_backtile->defaulttextures.base)) - draw_backtile->defaulttextures.base = R_LoadHiResTexture("gfx/menu/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); - if (!TEXLOADED(draw_backtile->defaulttextures.base)) - draw_backtile->defaulttextures.base = R_LoadHiResTexture("pics/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); + TEXDOWAIT(draw_backtile->defaulttextures->base); + if (!TEXLOADED(draw_backtile->defaulttextures->base)) + draw_backtile->defaulttextures->base = R_LoadHiResTexture("gfx/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); + if (!TEXLOADED(draw_backtile->defaulttextures->base)) + draw_backtile->defaulttextures->base = R_LoadHiResTexture("gfx/menu/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); + if (!TEXLOADED(draw_backtile->defaulttextures->base)) + draw_backtile->defaulttextures->base = R_LoadHiResTexture("pics/backtile", NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_NOWORKER); shader_draw_fill = R_RegisterShader("fill_opaque", SUF_NONE, "{\n" @@ -340,6 +340,7 @@ void R2D_Init(void) Cvar_ForceCallback(&gl_conback); Cvar_ForceCallback(&vid_conautoscale); Cvar_ForceCallback(&gl_font); + Cvar_ForceCallback(&gl_texturemode); Cvar_ForceCallback(&crosshair); Cvar_ForceCallback(&crosshaircolor); @@ -349,6 +350,8 @@ void R2D_Init(void) #endif R2D_Font_Changed(); + + R_NetgraphInit(); } mpic_t *R2D_SafeCachePic (const char *path) @@ -416,7 +419,7 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, { if (pic->passes[i].texgen == T_GEN_SINGLEMAP && pic->passes[i].anim_frames[0] && pic->passes[i].anim_frames[0]->status == TEX_LOADING) return; - if (pic->passes[i].texgen == T_GEN_DIFFUSE && pic->defaulttextures.base && pic->defaulttextures.base->status == TEX_LOADING) + if (pic->passes[i].texgen == T_GEN_DIFFUSE && pic->defaulttextures->base && pic->defaulttextures->base->status == TEX_LOADING) return; } @@ -440,7 +443,7 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, draw_mesh_st[3][0] = s1; draw_mesh_st[3][1] = t2; - BE_DrawMesh_Single(pic, &draw_mesh, NULL, &pic->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(pic, &draw_mesh, NULL, r2d_be_flags); } void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic) { @@ -453,7 +456,7 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic) { if (pic->passes[i].texgen == T_GEN_SINGLEMAP && pic->passes[i].anim_frames[0] && pic->passes[i].anim_frames[0]->status == TEX_LOADING) return; - if (pic->passes[i].texgen == T_GEN_DIFFUSE && pic->defaulttextures.base && pic->defaulttextures.base->status == TEX_LOADING) + if (pic->passes[i].texgen == T_GEN_DIFFUSE && pic->defaulttextures->base && pic->defaulttextures->base->status == TEX_LOADING) return; } @@ -463,7 +466,7 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic) Vector2Copy(texcoords[i], draw_mesh_st[i]); } - BE_DrawMesh_Single(pic, &draw_mesh, NULL, &pic->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(pic, &draw_mesh, NULL, r2d_be_flags); } /*draws a block of the current colour on the screen*/ @@ -482,9 +485,9 @@ void R2D_FillBlock(float x, float y, float w, float h) draw_mesh_xyz[3][1] = y+h; if (draw_mesh_colors[0][3] != 1) - BE_DrawMesh_Single(shader_draw_fill_trans, &draw_mesh, NULL, &shader_draw_fill_trans->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(shader_draw_fill_trans, &draw_mesh, NULL, r2d_be_flags); else - BE_DrawMesh_Single(shader_draw_fill, &draw_mesh, NULL, &shader_draw_fill->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(shader_draw_fill, &draw_mesh, NULL, r2d_be_flags); } void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) @@ -505,7 +508,7 @@ void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) draw_mesh.numvertexes = 2; draw_mesh.numindexes = 2; - BE_DrawMesh_Single(shader, &draw_mesh, NULL, &shader->defaulttextures, BEF_LINES); + BE_DrawMesh_Single(shader, &draw_mesh, NULL, BEF_LINES); draw_mesh.numvertexes = 4; draw_mesh.numindexes = 6; } @@ -559,7 +562,7 @@ void R2D_TransPicTranslate (float x, float y, int width, int height, qbyte *pic, "alphagen vertex\n" "}\n" "}\n"); - translate_shader->defaulttextures.base = translate_texture; + translate_shader->defaulttextures->base = translate_texture; } /* could avoid reuploading already translated textures but this func really isn't used enough anyway */ Image_Upload(translate_texture, TF_RGBA32, trans, NULL, 64, 64, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); @@ -662,7 +665,7 @@ void R2D_TileClear (float x, float y, float w, float h) draw_mesh_st[3][0] = newsl; draw_mesh_st[3][1] = newth; - BE_DrawMesh_Single(draw_backtile, &draw_mesh, NULL, &draw_backtile->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(draw_backtile, &draw_mesh, NULL, r2d_be_flags); } void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) @@ -1249,8 +1252,8 @@ void R2D_Crosshair_Update(void) return; else if (crosshairimage.string[0] && c == 1) { - shader_crosshair->defaulttextures.base = R_LoadHiResTexture (crosshairimage.string, "crosshairs", IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); - if (TEXVALID(shader_crosshair->defaulttextures.base)) + shader_crosshair->defaulttextures->base = R_LoadHiResTexture (crosshairimage.string, "crosshairs", IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); + if (TEXVALID(shader_crosshair->defaulttextures->base)) return; } else if (c <= 1) @@ -1261,7 +1264,7 @@ void R2D_Crosshair_Update(void) if (!TEXVALID(ch_int_texture)) ch_int_texture = Image_CreateTexture("***crosshair***", NULL, IF_UIPIC|IF_NOMIPMAP); - shader_crosshair->defaulttextures.base = ch_int_texture; + shader_crosshair->defaulttextures->base = ch_int_texture; Q_memset(crossdata, 0, sizeof(crossdata)); diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 195a3ff13..bbfe9cee1 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -113,7 +113,7 @@ static void R_Clutter_Insert_Soup(clutter_build_ctx_t *ctx, shader_t *shader, ve "}\n" "}\n" ); - shader->defaulttextures = os->defaulttextures; + *shader->defaulttextures = *os->defaulttextures; for (i = 0, soup = ctx->soups; i < ctx->numsoups; i++, soup++) diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c index 07c5810b5..f1bf31093 100644 --- a/engine/client/r_partset.c +++ b/engine/client/r_partset.c @@ -3263,6 +3263,118 @@ char *particle_set_q2part = "scalefactor 0.8\n" "}\n" +"r_part te_splashsparks\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xe0\n" +"}\n" +"r_part teq2_sparks\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 6\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xe0\n" +"}\n" +"r_part te_splashbluewater\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xb0\n" +"}\n" +"r_part te_splashbrownwater\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0x50\n" +"}\n" +"r_part te_splashslime\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xd0\n" +"}\n" +"r_part te_splashlava\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xe0\n" +"}\n" +"r_part te_splashblood\n" +"{\n" +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"count 1\n" +"scale 1\n" +"alpha 1\n" +"die 0.3 0.8\n" +"randomvel 20\n" +"orgadd 0 31\n" +"spawnorg 4\n" +"gravity 40\n" +"scalefactor 0.8\n" +"colorindex 0xe8\n" +"}\n" + + +//teq2_shield_sparks +//teq2_screen_sparks +//teq2_laser_sparks + + "r_part q2_smoke\n" "{\n" @@ -3374,6 +3486,22 @@ char *particle_set_q2part = "colorindex 0xe0\n" "}\n" + +"r_part teq2_bubbletrail\n" +"{\n" +/*blue spiral*/ +"texture \"classicparticle\"\n" +"tcoords 0 0 16 16 32\n" +"scale 0.5\n" +"alpha 1\n" +"scalefactor 0.8\n" +"step 32\n" +"spawnorg 2\n" +"spawnvel 5\n" +"die 1 1.2\n" +"colorindex 4 7\n" +"}\n" + "r_part TR_RAILTRAIL\n" "{\n" /*blue spiral*/ diff --git a/engine/client/render.h b/engine/client/render.h index cb9368bc6..df565d215 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -281,7 +281,7 @@ void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t * void R_LightArrays(const entity_t *entity, vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals, float scale); void R_DrawSkyChain (struct batch_s *batch); /*called from the backend, and calls back into it*/ -void R_InitSky (struct texnums_s *tn, const char *skyname, qbyte *src, unsigned int width, unsigned int height); /*generate q1 sky texnums*/ +void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int width, unsigned int height); /*generate q1 sky texnums*/ void R_Clutter_Emit(struct batch_s **batches); void R_Clutter_Purge(void); @@ -335,7 +335,6 @@ void R_SetSky(char *skyname); /*override all sky shaders*/ #if defined(GLQUAKE) void GLR_Init (void); -void GLR_ReInit (void); void GLR_InitTextures (void); void GLR_InitEfrags (void); void GLR_RenderView (void); // must set r_refdef first @@ -444,6 +443,15 @@ void *Mod_Extradata (struct model_s *mod); // handles caching void Mod_TouchModel (const char *name); void Mod_RebuildLightmaps (void); +typedef struct +{ + unsigned int *offsets; + unsigned short *extents; + unsigned char *styles; + unsigned char *shifts; +} lightmapoverrides_t; +void Mod_LoadLighting (struct model_s *loadmodel, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe, lightmapoverrides_t *overrides); + struct mleaf_s *Mod_PointInLeaf (struct model_s *model, float *p); void Mod_Think (void); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 7b7bbebe7..56072d756 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -60,6 +60,7 @@ static cvar_t gl_driver = CVARF ("gl_driver", "", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t gl_shadeq1_name = CVARD ("gl_shadeq1_name", "*", "Rename all surfaces from quake1 bsps using this pattern for the purposes of shader names."); extern cvar_t r_vertexlight; +extern cvar_t r_forceprogramify; cvar_t mod_md3flags = CVAR ("mod_md3flags", "1"); @@ -490,6 +491,7 @@ void GLRenderer_Init(void) // Cvar_Register (&gl_schematics, GLRENDEREROPTIONS); Cvar_Register (&r_vertexlight, GLRENDEREROPTIONS); + Cvar_Register (&r_forceprogramify, GLRENDEREROPTIONS); Cvar_Register (&gl_blend2d, GLRENDEREROPTIONS); @@ -1057,6 +1059,7 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) TRACE(("dbg: R_ApplyRenderer: old renderer closed\n")); pmove.numphysent = 0; + pmove.physents[0].model = NULL; if (qrenderer != QR_NONE) //graphics stuff only when not dedicated { @@ -1068,6 +1071,8 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) if (newr) Con_TPrintf("Setting mode %i*%i*%i*%i %s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->renderer->description); + vid.fullbright=0; + if (host_basepal) BZ_Free(host_basepal); host_basepal = (qbyte *)FS_LoadMallocFile ("gfx/palette.lmp", &sz); @@ -1093,11 +1098,7 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) { qbyte *colormap = (qbyte *)FS_LoadMallocFile ("gfx/colormap.lmp", NULL); - if (!colormap) - { - vid.fullbright=0; - } - else + if (colormap) { j = VID_GRADES-1; data = colormap + j*256; diff --git a/engine/client/sys_droid.c b/engine/client/sys_droid.c index 1005ae936..51f14107a 100644 --- a/engine/client/sys_droid.c +++ b/engine/client/sys_droid.c @@ -236,7 +236,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o Sys_Printf("Starting up (apk=%s, usr=%s)\n", args[2], parms.basedir); COM_InitArgv(parms.argc, parms.argv); - TL_InitLanguages(); + TL_InitLanguages(sys_basedir); #ifdef SERVERONLY SV_Init(&parms); #else diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 39e03397f..d08e44ab1 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -754,7 +754,6 @@ int main (int c, const char **v) parms.argc = c; parms.argv = v; COM_InitArgv(parms.argc, parms.argv); - TL_InitLanguages(); #ifdef __linux__ if (!COM_CheckParm("-nodumpstack")) @@ -789,6 +788,7 @@ int main (int c, const char **v) } */ #endif + TL_InitLanguages(parms.binarydir); isPlugin = !!COM_CheckParm("-plugin"); if (isPlugin) diff --git a/engine/client/sys_morphos.c b/engine/client/sys_morphos.c index 00edcee9f..997119c51 100755 --- a/engine/client/sys_morphos.c +++ b/engine/client/sys_morphos.c @@ -343,7 +343,7 @@ int main(int argc, char **argv) memset(&parms, 0, sizeof(parms)); COM_InitArgv(argc, argv); - TL_InitLanguages(); + TL_InitLanguages(""); parms.basedir = ""; parms.argc = argc; diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index bfca27a48..0cb4b2d21 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -475,7 +475,7 @@ int QDECL main(int argc, char **argv) COM_InitArgv (parms.argc, parms.argv); - TL_InitLanguages(); + TL_InitLanguages(parms.basedir); Sys_Printf ("Host_Init\n"); Host_Init (&parms); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 574e40263..249cc5839 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -4011,7 +4011,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin Q_snprintfz(sys_language, sizeof(sys_language), "%s", lang); } - TL_InitLanguages(); + TL_InitLanguages(parms.binarydir); //tprints are now allowed if (*cwd && cwd[strlen(cwd)-1] != '\\' && cwd[strlen(cwd)-1] != '/') diff --git a/engine/client/vid_headless.c b/engine/client/vid_headless.c index 7ec4c88c4..cb14309c7 100644 --- a/engine/client/vid_headless.c +++ b/engine/client/vid_headless.c @@ -148,7 +148,7 @@ static void Headless_BE_SelectMode (backendmode_t mode) static void Headless_BE_DrawMesh_List (shader_t *shader, int nummeshes, struct mesh_s **mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags) { } -static void Headless_BE_DrawMesh_Single (shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags) +static void Headless_BE_DrawMesh_Single (shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, unsigned int be_flags) { } static void Headless_BE_SubmitBatch (struct batch_s *batch) diff --git a/engine/common/common.h b/engine/common/common.h index 38a962890..95d0e4403 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -575,7 +575,7 @@ int version_number(void); char *version_string(void); -void TL_InitLanguages(void); +void TL_InitLanguages(char *langpath); //langpath is where the .po files can be found void TL_Shutdown(void); void T_FreeStrings(void); char *T_GetString(int num); diff --git a/engine/common/fs.c b/engine/common/fs.c index 482bf2285..fbde2df01 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -4191,6 +4191,25 @@ ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, q return man; } +qboolean FS_FixPath(char *path, size_t pathsize) +{ + size_t len = strlen(path); + if (len) + { + if (path[len-1] == '/') + return true; +#ifdef _WIN32 + if (path[len-1] == '\\') + return true; +#endif + if (len >= pathsize-1) + return false; + path[len] = '/'; + path[len+1] = 0; + } + return true; +} + //this is potentially unsafe. needs lots of testing. qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean allowbasedirchange) { @@ -4308,7 +4327,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean builtingame = true; if (!fixedbasedir && !FS_DirHasGame(newbasedir, i)) - if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_DirHasGame(realpath, i)) + if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasGame(realpath, i)) Q_strncpyz (newbasedir, realpath, sizeof(newbasedir)); break; } @@ -4319,7 +4338,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean { if (!builtingame && !fixedbasedir && !FS_DirHasAPackage(newbasedir, man)) { - if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_DirHasAPackage(realpath, man)) + if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasAPackage(realpath, man)) Q_strncpyz (newbasedir, realpath, sizeof(newbasedir)); #ifndef SERVERONLY else diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 86708d190..43535bcc5 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -56,7 +56,6 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, qbyte *mod_base, lump_t *l); qboolean Mod_LoadEdges (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm); qboolean Mod_LoadMarksurfaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm); qboolean Mod_LoadSurfedges (model_t *loadmodel, qbyte *mod_base, lump_t *l); -void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe); static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace); @@ -3870,7 +3869,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole char loadname[32]; qbyte *mod_base = (qbyte *)filein; - void (*buildmeshes)(model_t *mod, msurface_t *surf, void *cookie) = NULL; + void (*buildmeshes)(model_t *mod, msurface_t *surf, builddata_t *cookie) = NULL; qbyte *facedata = NULL; unsigned int facesize = 0; cminfo_t *prv; @@ -4188,7 +4187,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole noerrors = noerrors && Mod_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false); noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); if (noerrors) - Mod_LoadLighting (mod, mod_base, &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W); + Mod_LoadLighting (mod, mod_base, &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, NULL); noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[Q2LUMP_PLANES]); noerrors = noerrors && CModQ2_LoadTexInfo (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO], loadname); diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 01878053f..960af0b3d 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -400,7 +400,7 @@ int PM_StepSlideMove (qboolean in_air) } //FIXME gravitydir - if (in_air && originalvel[2] < 0) + if ((in_air || movevars.slidefix) && originalvel[2] < 0) VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0 PM_SlideMove (); @@ -770,7 +770,11 @@ void PM_AirMove (void) { if (movevars.slidefix) { - pmove.velocity[2] = min(pmove.velocity[2], 0); // bound above by 0 + if (DotProduct(pmove.velocity, pmove.gravitydir) < 0) + { + VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0 + //pmove.velocity[2] = min(pmove.velocity[2], 0); // bound above by 0 + } PM_Accelerate (wishdir, wishspeed, movevars.accelerate); // add gravity VectorMA(pmove.velocity, movevars.entgravity * movevars.gravity * frametime, pmove.gravitydir, pmove.velocity); @@ -938,47 +942,50 @@ void PM_CategorizePosition (void) //bsp objects marked as ladders mark regions to stand in to be classed as on a ladder. cont = PM_ExtraBoxContents(pmove.origin); + if (pmove.physents[0].model) + { #ifdef Q3BSPS - //q3 has surfaceflag-based ladders - if (pmove.physents[0].model->fromgame == fg_quake3) - { - trace_t t; - vec3_t flatforward, fwd1; - - flatforward[0] = forward[0]; - flatforward[1] = forward[1]; - flatforward[2] = 0; - VectorNormalize (flatforward); - - VectorMA (pmove.origin, 24, flatforward, fwd1); - - pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, 0, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t); - if (t.surface && t.surface->flags & Q3SURF_LADDER) + //q3 has surfaceflag-based ladders + if (pmove.physents[0].model->fromgame == fg_quake3) { - pmove.onladder = true; - pmove.onground = false; // too steep + trace_t t; + vec3_t flatforward, fwd1; + + flatforward[0] = forward[0]; + flatforward[1] = forward[1]; + flatforward[2] = 0; + VectorNormalize (flatforward); + + VectorMA (pmove.origin, 24, flatforward, fwd1); + + pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, 0, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t); + if (t.surface && t.surface->flags & Q3SURF_LADDER) + { + pmove.onladder = true; + pmove.onground = false; // too steep + } } - } #endif - //q2 has contents-based ladders - if ((cont & FTECONTENTS_LADDER) || ((cont & Q2CONTENTS_LADDER) && pmove.physents[0].model->fromgame == fg_quake2)) - { - trace_t t; - vec3_t flatforward, fwd1; - - flatforward[0] = forward[0]; - flatforward[1] = forward[1]; - flatforward[2] = 0; - VectorNormalize (flatforward); - - VectorMA (pmove.origin, 24, flatforward, fwd1); - - //if we hit a wall when going forwards and we are in a ladder region, then we are on a ladder. - t = PM_PlayerTrace(pmove.origin, fwd1, MASK_PLAYERSOLID); - if (t.fraction < 1) + //q2 has contents-based ladders + if ((cont & FTECONTENTS_LADDER) || ((cont & Q2CONTENTS_LADDER) && pmove.physents[0].model->fromgame == fg_quake2)) { - pmove.onladder = true; - pmove.onground = false; // too steep + trace_t t; + vec3_t flatforward, fwd1; + + flatforward[0] = forward[0]; + flatforward[1] = forward[1]; + flatforward[2] = 0; + VectorNormalize (flatforward); + + VectorMA (pmove.origin, 24, flatforward, fwd1); + + //if we hit a wall when going forwards and we are in a ladder region, then we are on a ladder. + t = PM_PlayerTrace(pmove.origin, fwd1, MASK_PLAYERSOLID); + if (t.fraction < 1) + { + pmove.onladder = true; + pmove.onground = false; // too steep + } } } @@ -1127,7 +1134,7 @@ void PM_NudgePosition (void) base[i] = ((int)(base[i]*8)) * 0.125; //if we're moving, allow that spot without snapping to any grid - if (pmove.velocity[0] || pmove.velocity[1] || pmove.velocity[2]) +// if (pmove.velocity[0] || pmove.velocity[1] || pmove.velocity[2]) if (PM_TestPlayerPosition (pmove.origin, false)) return; @@ -1266,8 +1273,8 @@ were contacted during the move. */ void PM_PlayerMove (float gamespeed) { -// int i; -// int tmp; //for rounding + int i; + int tmp; //for rounding frametime = pmove.cmd.msec * 0.001*gamespeed; pmove.numtouch = 0; @@ -1330,6 +1337,16 @@ void PM_PlayerMove (float gamespeed) else PM_AirMove (); + //round to network precision + for (i = 0; i < 3; i++) + { + tmp = floor(pmove.velocity[i]*8 + 0.5); + pmove.velocity[i] = tmp/8.0; + tmp = floor(pmove.origin[i]*8 + 0.5); + pmove.origin[i] = tmp/8.0; + } + PM_NudgePosition (); + // set onground, watertype, and waterlevel for final spot PM_CategorizePosition (); @@ -1340,15 +1357,4 @@ void PM_PlayerMove (float gamespeed) { PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1); } - -/* - //round to network precision - for (i = 0; i < 3; i++) - { - tmp = floor(pmove.velocity[i]*8 + 0.5); - pmove.velocity[i] = tmp/8.0; - tmp = floor(pmove.origin[i]*8 + 0.5); - pmove.origin[i] = tmp/8.0; - } -*/ } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 817b0730a..1a48b8b41 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -4869,7 +4869,7 @@ void QCBUILTIN PF_localcmd (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob char *str; str = PF_VarString(prinst, 0, pr_globals); - if (developer.ival) + if (developer.ival >= 2) { PR_StackTrace(prinst, false); Con_Printf("localcmd: %s\n", str); diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 31f1bec9d..38ea1cff5 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -1162,7 +1162,6 @@ struct fragmentdecal_s void (*callback)(void *ctx, vec3_t *fte_restrict points, size_t numpoints, shader_t *shader); void *ctx; }; -typedef struct fragmentdecal_s fragmentdecal_t; //#define SHOWCLIPS //#define FRAGMENTASTRIANGLES //works, but produces more fragments. diff --git a/engine/common/translate.c b/engine/common/translate.c index e29675c95..14381ebe1 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -10,6 +10,7 @@ char sys_language[64] = ""; +static char langpath[MAX_OSPATH] = ""; struct language_s languages[MAX_LANGUAGES]; static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue) @@ -62,7 +63,7 @@ static int TL_LoadLanguage(char *lang) return 0; if (*lang) - f = FS_OpenVFS(va("fteqw.%s.po", lang), "rb", FS_BINARYPATH); + f = FS_OpenVFS(va("%sfteqw.%s.po", langpath, lang), "rb", FS_SYSTEM); else f = NULL; if (!f && *lang) @@ -88,11 +89,13 @@ int TL_FindLanguage(const char *lang) } //need to set up default languages for any early prints before cvars are inited. -void TL_InitLanguages(void) +void TL_InitLanguages(char *newlangpath) { int i; char *lang; + Q_strncpyz(langpath, newlangpath, sizeof(langpath)); + //lang can override any environment or system settings. if ((i = COM_CheckParm("-lang"))) Q_strncpyz(sys_language, com_argv[i+1], sizeof(sys_language)); diff --git a/engine/d3d/d3d11_backend.c b/engine/d3d/d3d11_backend.c index a14b0f5d3..c422211b9 100644 --- a/engine/d3d/d3d11_backend.c +++ b/engine/d3d/d3d11_backend.c @@ -916,13 +916,13 @@ static void SelectPassTexture(unsigned int tu, const shaderpass_t *pass) BindTexture(tu, shaderstate.curtexnums->base); break; case T_GEN_NORMALMAP: - if (TEXVALID(shaderstate.curtexnums->bump)) + if (TEXLOADED(shaderstate.curtexnums->bump)) BindTexture(tu, shaderstate.curtexnums->bump); else BindTexture(tu, missing_texture_normal); break; case T_GEN_SPECULAR: - if (TEXVALID(shaderstate.curtexnums->specular)) + if (TEXLOADED(shaderstate.curtexnums->specular)) BindTexture(tu, shaderstate.curtexnums->specular); else BindTexture(tu, missing_texture_gloss); @@ -1771,11 +1771,11 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert for (i = 0; i < lastpass; i++) { - if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay)) continue; - if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay)) continue; - if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright)) continue; break; } @@ -1792,11 +1792,11 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert /*activate tmus*/ for (passno = 0; passno < lastpass; passno++) { - if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay)) continue; - if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay)) continue; - if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright)) continue; SelectPassTexture(tmu, pass+passno); @@ -1909,15 +1909,15 @@ static void BE_RenderMeshProgram(const shader_t *s, unsigned int vertcount, unsi program_t *p = s->prog; - if (TEXVALID(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert) + if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert) perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert) + if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert) perm |= PERMUTATION_FULLBRIGHT; - if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay))) + if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) perm |= PERMUTATION_UPPERLOWER; if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert) perm |= PERMUTATION_FOG; -// if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert) +// if (r_glsl_offsetmapping.ival && TEXLOADED(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert) // perm |= PERMUTATION_OFFSET; BE_ApplyUniforms(p, perm); @@ -2908,19 +2908,25 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) void D3D11BE_SubmitBatch(batch_t *batch) { + shader_t *shader = batch->shader; shaderstate.nummeshes = batch->meshes - batch->firstmesh; if (!shaderstate.nummeshes) return; + shaderstate.curbatch = batch; + shaderstate.batchvbo = batch->vbo; + shaderstate.meshlist = batch->mesh + batch->firstmesh; + shaderstate.curshader = shader; if (shaderstate.curentity != batch->ent) { BE_RotateForEntity(batch->ent, batch->ent->model); shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; } - shaderstate.curbatch = batch; - shaderstate.batchvbo = batch->vbo; - shaderstate.meshlist = batch->mesh + batch->firstmesh; - shaderstate.curshader = batch->shader; - shaderstate.curtexnums = batch->skin?batch->skin:&batch->shader->defaulttextures; + if (batch->skin) + shaderstate.curtexnums = batch->skin; + else if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.flags = batch->flags; if (!shaderstate.batchvbo) @@ -2938,7 +2944,12 @@ void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, v shaderstate.curbatch = &shaderstate.dummybatch; shaderstate.batchvbo = vbo; shaderstate.curshader = shader; - shaderstate.curtexnums = texnums; + if (texnums) + shaderstate.curtexnums = texnums; + else if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.meshlist = meshlist; shaderstate.nummeshes = nummeshes; shaderstate.flags = beflags; @@ -2954,13 +2965,16 @@ void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, v BE_DrawMeshChain_Internal(); } -void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsigned int beflags) { shaderstate.curbatch = &shaderstate.dummybatch; shaderstate.batchvbo = vbo; shaderstate.curtime = realtime; shaderstate.curshader = shader; - shaderstate.curtexnums = texnums?texnums:&shader->defaulttextures; + if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.meshlist = &meshchain; shaderstate.nummeshes = 1; shaderstate.flags = beflags; diff --git a/engine/d3d/d3d11_image.c b/engine/d3d/d3d11_image.c index 8645e945c..04f8a3287 100644 --- a/engine/d3d/d3d11_image.c +++ b/engine/d3d/d3d11_image.c @@ -110,6 +110,8 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int data qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) { + int bytesperpixel = 4; + int bcbytes = 0; HRESULT hr; D3D11_TEXTURE2D_DESC tdesc = {0}; D3D11_SUBRESOURCE_DATA subresdesc[sizeof(mips->mip) / sizeof(mips->mip[0])]; @@ -150,54 +152,69 @@ qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) case PTI_DEPTH16: tdesc.Format = DXGI_FORMAT_D16_UNORM; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + bytesperpixel = 2; break; case PTI_DEPTH24: tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + bytesperpixel = 3; break; case PTI_DEPTH32: tdesc.Format = DXGI_FORMAT_D32_FLOAT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + bytesperpixel = 4; break; case PTI_DEPTH24_8: tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + bytesperpixel = 4; break; case PTI_RGB565: tdesc.Format = DXGI_FORMAT_B5G6R5_UNORM; + bytesperpixel = 2; break; // case PTI_RGBA5551: // tdesc.Format = DXGI_FORMAT_A1B5G5R5_UNORM; +// bytesperpixel = 2; // break; case PTI_ARGB1555: tdesc.Format = DXGI_FORMAT_B5G5R5A1_UNORM; + bytesperpixel = 2; break; case PTI_RGBA4444: tdesc.Format = DXGI_FORMAT_B4G4R4A4_UNORM; + bytesperpixel = 2; break; // case PTI_ARGB4444: // tdesc.Format = DXGI_FORMAT_A4B4G4R4_UNORM; +// bytesperpixel = 2; // break; case PTI_RGBA8: case PTI_RGBX8: //d3d11 has no alphaless format. be sure to proprly disable alpha in the shader. tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + bytesperpixel = 4; break; case PTI_BGRA8: tdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + bytesperpixel = 4; break; case PTI_BGRX8: tdesc.Format = DXGI_FORMAT_B8G8R8X8_UNORM; + bytesperpixel = 4; break; case PTI_S3RGB1: //d3d11 provides no way to disable alpha with dxt1. be sure to proprly disable alpha in the shader. case PTI_S3RGBA1: tdesc.Format = DXGI_FORMAT_BC1_UNORM; + bcbytes = 8; break; case PTI_S3RGBA3: tdesc.Format = DXGI_FORMAT_BC2_UNORM; + bcbytes = 16; break; case PTI_S3RGBA5: tdesc.Format = DXGI_FORMAT_BC3_UNORM; + bcbytes = 16; break; } @@ -212,8 +229,16 @@ qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) for (i = 0; i < mips->mipcount; i++) { subresdesc[i].pSysMem = mips->mip[i].data; - subresdesc[i].SysMemPitch = mips->mip[i].width*4; - subresdesc[i].SysMemSlicePitch = mips->mip[i].width*mips->mip[i].height*4; + if (bcbytes) + { + subresdesc[i].SysMemPitch = ((mips->mip[i].width+3)/4) * bcbytes; + subresdesc[i].SysMemSlicePitch = mips->mip[i].datasize; + } + else + { + subresdesc[i].SysMemPitch = mips->mip[i].width*bytesperpixel; + subresdesc[i].SysMemSlicePitch = mips->mip[i].datasize;//mips->mip[i].width*mips->mip[i].height*bytesperpixel; + } } tdesc.MipLevels = i/tdesc.ArraySize; } diff --git a/engine/d3d/d3d11_shader.c b/engine/d3d/d3d11_shader.c index 36f697e6d..34c8a61bd 100644 --- a/engine/d3d/d3d11_shader.c +++ b/engine/d3d/d3d11_shader.c @@ -409,6 +409,8 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned "s_paletted", "s_shadowmap", "s_projectionmap", + "s_reflectcube", + "s_reflectmask", "s_lightmap", "s_deluxmap" #if MAXRLIGHTMAPS > 1 @@ -612,7 +614,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned { int tmu; D3D11_SHADER_INPUT_BIND_DESC bdesc = {0}; - for (i = prog->numsamplers; i < 8; i++) + for (i = prog->numsamplers; i < be_maxpasses; i++) { if (SUCCEEDED(freflect->lpVtbl->GetResourceBindingDescByName(freflect, va("t_%i", i), &bdesc))) prog->numsamplers = i+1; diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 295305527..4e3ef2a00 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -281,17 +281,17 @@ static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) int *filter = (flags & SHADER_PASS_UIPIC)?shaderstate.picfilter:shaderstate.mipfilter; if ((filter[2] && !(flags & SHADER_PASS_NEAREST)) || (flags & SHADER_PASS_LINEAR)) - mag = D3DTEXF_LINEAR; + mag = D3DTEXF_ANISOTROPIC;//D3DTEXF_LINEAR; else mag = D3DTEXF_POINT; if (filter[1] == -1 || (flags & IF_NOMIPMAP)) mip = D3DTEXF_NONE; else if ((filter[1] && !(flags & SHADER_PASS_NEAREST)) || (flags & SHADER_PASS_LINEAR)) - mip = D3DTEXF_LINEAR; + mip = D3DTEXF_ANISOTROPIC;//D3DTEXF_LINEAR; else mip = D3DTEXF_POINT; if ((filter[0] && !(flags & SHADER_PASS_NEAREST)) || (flags & SHADER_PASS_LINEAR)) - min = D3DTEXF_LINEAR; + min = D3DTEXF_ANISOTROPIC;//D3DTEXF_LINEAR; else min = D3DTEXF_POINT; @@ -313,6 +313,8 @@ void D3D9_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3] { shaderstate.tmuflags[i] = ~shaderstate.tmuflags[i]; BE_ApplyTMUState(i, ~shaderstate.tmuflags[i]); + + IDirect3DDevice9_SetSamplerState(pD3DDev9, i, D3DSAMP_MAXANISOTROPY, anis); } } @@ -1604,11 +1606,11 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert for (i = 0; i < lastpass; i++) { - if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay)) continue; - if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay)) continue; - if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright)) continue; break; } @@ -1625,11 +1627,11 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert /*activate tmus*/ for (passno = 0; passno < lastpass; passno++) { - if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXVALID(shaderstate.curtexnums->upperoverlay)) + if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay)) continue; - if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXVALID(shaderstate.curtexnums->loweroverlay)) + if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay)) continue; - if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXVALID(shaderstate.curtexnums->fullbright)) + if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright)) continue; SelectPassTexture(tmu, pass+passno); @@ -1841,14 +1843,14 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i perm |= PERMUTATION_BUMPMAP; if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert) perm |= PERMUTATION_FULLBRIGHT; - if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay))) + if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) perm |= PERMUTATION_UPPERLOWER; if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert) perm |= PERMUTATION_FOG; if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.hlsl.vert && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff) perm |= PERMUTATION_FRAMEBLEND; - if (p->permu[perm|PERMUTATION_DELUXE].handle.hlsl.vert && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) - perm |= PERMUTATION_DELUXE; +// if (p->permu[perm|PERMUTATION_DELUXE].handle.hlsl.vert && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) +// perm |= PERMUTATION_DELUXE; if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.hlsl.vert) perm |= PERMUTATION_LIGHTSTYLES; @@ -2740,6 +2742,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) void D3D9BE_SubmitBatch(batch_t *batch) { + shader_t *shader = batch->shader; shaderstate.nummeshes = batch->meshes - batch->firstmesh; if (!shaderstate.nummeshes) return; @@ -2750,8 +2753,13 @@ void D3D9BE_SubmitBatch(batch_t *batch) } shaderstate.batchvbo = batch->vbo; shaderstate.meshlist = batch->mesh + batch->firstmesh; - shaderstate.curshader = batch->shader; - shaderstate.curtexnums = batch->skin?batch->skin:&batch->shader->defaulttextures; + shaderstate.curshader = shader; + if (batch->skin) + shaderstate.curtexnums = batch->skin; + else if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.curbatch = batch; shaderstate.flags = batch->flags; if ((unsigned)batch->lightmap[0] < (unsigned)numlightmaps) @@ -2776,12 +2784,15 @@ void D3D9BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vb BE_DrawMeshChain_Internal(); } -void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsigned int beflags) { shaderstate.batchvbo = vbo; shaderstate.curtime = realtime; shaderstate.curshader = shader; - shaderstate.curtexnums = texnums?texnums:&shader->defaulttextures; + if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.curlightmap = r_nulltex; shaderstate.meshlist = &meshchain; shaderstate.nummeshes = 1; @@ -2800,8 +2811,6 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) if (batch->buildmeshes) batch->buildmeshes(batch); - else if (batch->texture) - batch->skin = &batch->shader->defaulttextures; if (batch->shader->flags & SHADER_NODLIGHT) if (shaderstate.mode == BEM_LIGHT) diff --git a/engine/d3d/d3d_image.c b/engine/d3d/d3d_image.c index 36d0d9300..836b5abbb 100644 --- a/engine/d3d/d3d_image.c +++ b/engine/d3d/d3d_image.c @@ -28,6 +28,7 @@ qboolean D3D9_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) IDirect3DTexture9 *dt; qboolean swap = false; unsigned int pixelsize = 4; + unsigned int blocksize = 0; switch(mips->encoding) { @@ -67,15 +68,17 @@ qboolean D3D9_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) //too lazy to support these for now case PTI_S3RGB1: case PTI_S3RGBA1: //d3d doesn't distinguish between these -// fmt = D3DFMT_DXT1; -// break; + fmt = D3DFMT_DXT1; + blocksize = 8; + break; case PTI_S3RGBA3: -// fmt = D3DFMT_DXT3; -// break; + fmt = D3DFMT_DXT3; + blocksize = 16; + break; case PTI_S3RGBA5: -// fmt = D3DFMT_DXT5; -// break; - return false; + fmt = D3DFMT_DXT5; + blocksize = 16; + break; default: //no idea return false; @@ -96,7 +99,13 @@ qboolean D3D9_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) IDirect3DTexture9_LockRect(dt, i, &lock, NULL, D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD); //can't do it in one go. pitch might contain padding or be upside down. - if (swap) + if (blocksize) + { + if (lock.Pitch == ((mips->mip[i].width+3)/4)*blocksize) + //for (y = 0, out = lock.pBits, in = mips->mip[i].data; y < mips->mip[i].height; y++, out += lock.Pitch, in += mips->mip[i].width*pixelsize) + memcpy(lock.pBits, mips->mip[i].data, mips->mip[i].datasize); + } + else if (swap) { for (y = 0, out = lock.pBits, in = mips->mip[i].data; y < mips->mip[i].height; y++, out += lock.Pitch, in += mips->mip[i].width*4) { diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index c3b05af5c..2bd29af7b 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -264,6 +264,8 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv "s_paletted", "s_shadowmap", "s_projectionmap", + "s_reflectcube", + "s_reflectmask", "s_lightmap", "s_deluxmap" #if MAXRLIGHTMAPS > 1 @@ -275,6 +277,8 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv ,"s_deluxmap3" #endif }; +#define ALTLIGHTMAPSAMP 13 +#define ALTDELUXMAPSAMP 16 prog->numparams = 0; @@ -355,10 +359,10 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv } //multiple lightmaps is kinda hacky. if any are set, all must be. - if (prog->defaulttextures & ((1u<<11) | (1u<<12) | (1u<<13))) - prog->defaulttextures |=((1u<<11) | (1u<<12) | (1u<<13)); - if (prog->defaulttextures & ((1u<<14) | (1u<<15) | (1u<<16))) - prog->defaulttextures |=((1u<<14) | (1u<<15) | (1u<<16)); + if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)))) + prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))); + if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)))) + prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))); if (prog->defaulttextures) { diff --git a/engine/droid/src/com/fteqw/FTEDroidActivity.java b/engine/droid/src/com/fteqw/FTEDroidActivity.java index c9151df31..4b201c72b 100644 --- a/engine/droid/src/com/fteqw/FTEDroidActivity.java +++ b/engine/droid/src/com/fteqw/FTEDroidActivity.java @@ -453,6 +453,31 @@ public class FTEDroidActivity extends Activity } } +/* private FTEJoystickInputEvent joystickevent; + class FTEJoystickInputEvent + { + //API level 12+ + public boolean go(MotionEvent event) + { + if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) + { + //FIXME: get MotionRange values from the device, so we can query the ideal size of the deadzone + FTEDroidEngine.axischange(0, event.getAxisValue(MotionEvent.AXIS_X)); + FTEDroidEngine.axischange(1, event.getAxisValue(MotionEvent.AXIS_Y)); + FTEDroidEngine.axischange(2, event.getAxisValue(MotionEvent.AXIS_Z)); + FTEDroidEngine.axischange(3, event.getAxisValue(MotionEvent.AXIS_RZ)); + FTEDroidEngine.axischange(4, event.getAxisValue(MotionEvent.AXIS_HAT_X)); + FTEDroidEngine.axischange(5, event.getAxisValue(MotionEvent.AXIS_HAT_Y)); + FTEDroidEngine.axischange(6, event.getAxisValue(MotionEvent.AXIS_LTRIGGER)); + FTEDroidEngine.axischange(7, event.getAxisValue(MotionEvent.AXIS_RTRIGGER)); + FTEDroidEngine.axischange(8, event.getAxisValue(MotionEvent.AXIS_BREAK)); + FTEDroidEngine.axischange(9, event.getAxisValue(MotionEvent.AXIS_GAS)); + return true; + } + return false; + } + } +*/ private FTELegacyInputEvent inputevent; class FTEMultiTouchInputEvent extends FTELegacyInputEvent { @@ -537,6 +562,9 @@ public class FTEDroidActivity extends Activity inputevent = new FTEMultiTouchInputEvent(); else inputevent = new FTELegacyInputEvent(); + +// if (android.os.Build.VERSION.SDK_INT >= 12) +// joystickevent = new FTEJoystickInputEvent(); rndr = new FTERenderer(this, context); setRenderer(rndr); @@ -574,6 +602,16 @@ public class FTEDroidActivity extends Activity private static final int K_SEARCH = 242; private static final int K_VOLUP = 243; private static final int K_VOLDOWN = 244; + + private static final int K_JOY1 = 203; + private static final int K_JOY2 = 204; + private static final int K_JOY3 = 205; + private static final int K_JOY4 = 206; + private static final int K_AUX1 = 207; + private static final int K_AUX2 = 208; + private static final int K_AUX3 = 209; + private static final int K_AUX4 = 210; + private int mapKey(int acode, int unicode) { switch(acode) @@ -603,6 +641,24 @@ public class FTEDroidActivity extends Activity return K_VOLDOWN; //"voldown" case KeyEvent.KEYCODE_VOLUME_UP: return K_VOLUP; //"volup" + + case 99/*KeyEvent.KEYCODE_BUTTON_X*/: + return K_JOY1; + case 96/*KeyEvent.KEYCODE_BUTTON_A*/: + return K_JOY2; + case 100/*KeyEvent.KEYCODE_BUTTON_Y*/: + return K_JOY3; + case 97/*KeyEvent.KEYCODE_BUTTON_B*/: + return K_JOY4; + case 102/*KeyEvent.KEYCODE_BUTTON_L1*/: + return K_AUX1; + case 103/*KeyEvent.KEYCODE_BUTTON_R1*/: + return K_AUX2; + case 106/*KeyEvent.KEYCODE_BUTTON_THUMBL*/: + return K_AUX3; + case 107/*KeyEvent.KEYCODE_BUTTON_THUMBR*/: + return K_AUX4; + default: if (unicode < 128) return Character.toLowerCase(unicode); @@ -625,6 +681,19 @@ public class FTEDroidActivity extends Activity sendKey(false, mapKey(keyCode, uc), uc); return true; } + +/* + @Override + public boolean onGenericMotionEvent(android.view.MotionEvent event) + { + if (joystickevent) + if (joystickevent.go(event)) + return true; + //FIXME: handle mouse and mousewheel + return false; + } +*/ + /* @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 1d99dacb4..c1cc77da2 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -232,7 +232,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext) memset(registeredskins + numregisteredskins, 0, (newn-numregisteredskins)*sizeof(*registeredskins)); numregisteredskins = newn; } - + skin = Z_Malloc(sizeof(*skin) - sizeof(skin->mappings) + sizeof(skin->mappings[0])*4); skin->maxmappings = 4; Q_strncpyz(skin->skinname, skinname, sizeof(skin->skinname)); @@ -261,7 +261,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext) Q_strncpyz(shadername, com_token, sizeof(shadername)); skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname); R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader); - skin->mappings[skin->nummappings].texnums = skin->mappings[skin->nummappings].shader->defaulttextures; + skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures; skin->nummappings++; } } @@ -280,7 +280,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext) Q_strncpyz(shadername, com_token, sizeof(shadername)); skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname); R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader); - skin->mappings[skin->nummappings].texnums = skin->mappings[skin->nummappings].shader->defaulttextures; + skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures; for(;;) { @@ -351,7 +351,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext) Q_strncpyz(shadername, com_token, sizeof(shadername)); skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname); R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader); - skin->mappings[skin->nummappings].texnums = skin->mappings[skin->nummappings].shader->defaulttextures; + skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures; skin->nummappings++; } } @@ -596,8 +596,8 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e s = R_RegisterSkin(va("gfx/skin%d.lmp", e->skinnum), NULL); if (s) { - if (!TEXVALID(s->defaulttextures.base)) - s->defaulttextures.base = R_LoadHiResTexture(va("gfx/skin%d.lmp", e->skinnum), NULL, 0); +// if (!TEXVALID(s->defaulttextures.base)) +// s->defaulttextures.base = R_LoadHiResTexture(va("gfx/skin%d.lmp", e->skinnum), NULL, 0); return s; } } @@ -702,9 +702,10 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e { if (!plskin) { + texnums_t *tex = shader->defaulttextures; //do this for the loading case too, in the hope that it'll avoid generating a per-player skin at all - if ((shader->defaulttextures.loweroverlay && (shader->defaulttextures.loweroverlay->status == TEX_LOADING || shader->defaulttextures.loweroverlay->status == TEX_LOADED)) || - (shader->defaulttextures.upperoverlay && (shader->defaulttextures.upperoverlay->status == TEX_LOADING || shader->defaulttextures.upperoverlay->status == TEX_LOADED))) + if ((tex->loweroverlay && (tex->loweroverlay->status == TEX_LOADING || tex->loweroverlay->status == TEX_LOADED)) || + (tex->upperoverlay && (tex->upperoverlay->status == TEX_LOADING || tex->upperoverlay->status == TEX_LOADED))) return shader; } if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl.handle && !h2playertranslations) @@ -727,7 +728,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e } //colourmap isn't present yet. - cm = BZ_Malloc(sizeof(*cm)); + cm = Z_Malloc(sizeof(*cm)); *forcedtex = &cm->texnum; Q_strncpyz(cm->name, skinname, sizeof(cm->name)); Hash_Add(&skincolourmapped, cm->name, cm, &cm->bucket); @@ -736,20 +737,13 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e cm->pclass = pc; //is this needed? surely it'll be baked as part of the modelname? cm->skinnum = e->skinnum; cm->subframe = subframe; - cm->texnum.fullbright = r_nulltex; - cm->texnum.base = r_nulltex; - cm->texnum.bump = r_nulltex; - cm->texnum.specular = r_nulltex; - cm->texnum.loweroverlay = r_nulltex; - cm->texnum.upperoverlay = r_nulltex; - cm->texnum.paletted = r_nulltex; //q2 has no surfaces in its player models, so don't crash from that //note that q2 should also always have a custom skin set. its not our problem (here) if it doesn't. if (!shader) shader = R_RegisterSkin(skinname, NULL); - cm->texnum.bump = shader->defaulttextures.bump; //can't colour bumpmapping + cm->texnum.bump = shader->defaulttextures->bump; //can't colour bumpmapping if (plskin) { /*q1 only reskins the player model, not gibbed heads (which have the same colourmap)*/ @@ -764,6 +758,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e cm->texnum.base = plskin->textures.base; cm->texnum.fullbright = plskin->textures.fullbright; cm->texnum.specular = plskin->textures.specular; + cm->texnum.paletted = r_nulltex; + cm->texnum.reflectcube = r_nulltex; + cm->texnum.reflectmask = r_nulltex; return shader; } } @@ -959,9 +956,11 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e cm->texnum.base = R_LoadTexture(va("base$%x$%x$%i$%i$%i$%s", tc, bc, cm->skinnum, subframe, pc, cm->name), scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, IF_NOMIPMAP); - cm->texnum.bump = shader->defaulttextures.bump; - cm->texnum.fullbright = shader->defaulttextures.fullbright; - cm->texnum.specular = shader->defaulttextures.specular; + cm->texnum.bump = shader->defaulttextures->bump; + cm->texnum.fullbright = shader->defaulttextures->fullbright; + cm->texnum.specular = shader->defaulttextures->specular; + cm->texnum.reflectcube = shader->defaulttextures->reflectcube; + cm->texnum.reflectmask = shader->defaulttextures->reflectmask; /*if (!h2playertranslations) { qboolean valid = false; @@ -1044,7 +1043,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e else { /*model has no original skin info and thus cannot be reskinned, copy over the default textures so that the skincache doesn't break things when it gets reused*/ - cm->texnum = shader->defaulttextures; + cm->texnum = *shader->defaulttextures; } return shader; } @@ -1058,7 +1057,13 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e skins += e->skinnum; else { - Con_DPrintf("Skin number out of range (%u > %u - %s)\n", e->skinnum, inf->numskins, model->name); + if (developer.ival) + { + static int lastframe; + if (lastframe != r_framecount && lastframe != r_framecount-1) //patented anti-spam technology!... actually, I wonder if it would actually be eligable for a patent. + Con_DPrintf("Skin number out of range (%u >= %u - %s)\n", e->skinnum, inf->numskins, model->name); + lastframe = r_framecount; + } if (!inf->numskins) return NULL; } @@ -1504,7 +1509,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) regshader = GL_ChooseSkin(inf, clmodel, surfnum, e, &skin); if (!regshader) continue; - skin = skin?skin:®shader->defaulttextures; + skin = skin?skin:NULL; shader = e->forcedshader?e->forcedshader:regshader; if (shader) { @@ -2006,7 +2011,7 @@ void GL_GenerateNormals(float *orgs, float *normals, int *indicies, int numtris, -#ifdef Q3CLIENT +#if defined(Q2CLIENT) || defined(Q3CLIENT) //q3 lightning gun / q3 railgun / q2 beams static void R_Beam_GenerateTrisoup(entity_t *e, int bemode) { @@ -2020,23 +2025,18 @@ static void R_Beam_GenerateTrisoup(entity_t *e, int bemode) float scale, length; vec3_t dir, v, cr; - if (e->forcedshader) - { - shader = e->forcedshader; - if (!shader) - shader = R_RegisterShader("q2beam", SUF_NONE, + shader = e->forcedshader; + if (!shader) + shader = R_RegisterShader("q2beam", SUF_NONE, + "{\n" "{\n" - "{\n" - "map $whiteimage\n" - "rgbgen vertex\n" - "alphagen vertex\n" - "blendfunc blend\n" - "}\n" + "map $whiteimage\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc blend\n" "}\n" - ); - } - else - return; + "}\n" + ); batchflags = 0; // if (e->flags & RF_NOSHADOW) @@ -2114,9 +2114,12 @@ static void R_Beam_GenerateTrisoup(entity_t *e, int bemode) t->numvert += 4; cl_numstrisvert += 4; - scale = e->scale*10; + scale = e->scale*5; if (!scale) - scale = 10; + scale = 5; + + if (shader->flags & SHADER_CULL_FRONT) + scale *= -1; VectorSubtract(e->origin, e->oldorigin, dir); length = Length(dir); @@ -2452,7 +2455,7 @@ static void BE_GenPolyBatches(batch_t **batches) b->mesh = NULL; b->firstmesh = 0; b->meshes = 1; - b->skin = &shader->defaulttextures; + b->skin = NULL; b->texture = NULL; b->shader = shader; for (j = 0; j < MAXRLIGHTMAPS; j++) @@ -2592,14 +2595,14 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo R_Sprite_GenerateTrisoup(ent, bemode); break; -#ifdef Q3CLIENT case RT_BEAM: case RT_RAIL_RINGS: case RT_LIGHTNING: case RT_RAIL_CORE: +#if defined(Q2CLIENT) || defined(Q3CLIENT) R_Beam_GenerateTrisoup(ent, bemode); - continue; #endif + break; case RT_POLY: /*not implemented*/ diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index b620a7d35..ce5cb4947 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -36,6 +36,10 @@ extern texid_t missing_texture_normal; extern texid_t scenepp_postproc_cube; extern texid_t r_whiteimage; +#ifndef GLSLONLY +static void GenerateTCMods(const shaderpass_t *pass, int passnum); +#endif + static const char LIGHTPASS_SHADER[] = "\ {\n\ program rtlight%s\n\ @@ -674,8 +678,8 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend break; #endif case VATTR_TEXCOORD: - GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); - qglVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, shaderstate.sourcevbo->texcoord.gl.addr); + GL_SelectVBO(shaderstate.pendingtexcoordvbo[0]); + qglVertexAttribPointer(VATTR_TEXCOORD, shaderstate.pendingtexcoordparts[0], GL_FLOAT, GL_FALSE, 0, shaderstate.pendingtexcoordpointer[0]); break; case VATTR_LMCOORD: if (!shaderstate.sourcevbo->lmcoord[0].gl.vbo && !shaderstate.sourcevbo->lmcoord[0].gl.addr) @@ -1170,6 +1174,12 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) case T_GEN_FULLBRIGHT: t = shaderstate.curtexnums->fullbright; break; + case T_GEN_REFLECTCUBE: + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, shaderstate.curtexnums->reflectcube); + return; + case T_GEN_REFLECTMASK: + t = shaderstate.curtexnums->reflectmask; + break; case T_GEN_SHADOWMAP: t = shaderstate.curshadowmap; break; @@ -3360,8 +3370,10 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas perm |= PERMUTATION_UPPERLOWER; if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl.handle) perm |= PERMUTATION_FOG; - if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) - perm |= PERMUTATION_DELUXE; +// if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) +// perm |= PERMUTATION_DELUXE; + if (TEXLOADED(shaderstate.curtexnums->reflectcube) && p->permu[perm|PERMUTATION_REFLECTCUBEMASK].handle.glsl.handle) + perm |= PERMUTATION_REFLECTCUBEMASK; #if MAXRLIGHTMAPS > 1 if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl.handle) perm |= PERMUTATION_LIGHTSTYLES; @@ -3380,7 +3392,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas BE_Program_Set_Attributes(p, perm, i); BE_SendPassBlendDepthMask(pass->shaderbits); - BE_EnableShaderAttributes(p->permu[perm].attrmask, shaderstate.sourcevbo->vao); + #ifndef GLSLONLY if (!p->nofixedcompat) { @@ -3399,6 +3411,17 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas else #endif { +#ifndef GLSLONLY + if (pass->numtcmods) + GenerateTCMods(pass, 0); + else +#endif + { + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + } + for (i = 0; i < pass->numMergedPasses; i++) { Shader_BindTextureForPass(i, pass+i); @@ -3418,6 +3441,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); shaderstate.lastpasstmus = i; //in case it was already lower } + BE_EnableShaderAttributes(p->permu[perm].attrmask, shaderstate.sourcevbo->vao); BE_SubmitMeshChain(p->permu[perm].handle.glsl.usetesselation); } @@ -4286,6 +4310,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ { shaderstate.curbatch = &shaderstate.dummybatch; shaderstate.curshader = shader->remapto; + if (!vbo) { mesh_t *m; @@ -4294,7 +4319,12 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ if (shaderstate.curentity != &r_worldentity) GLBE_SelectEntity(&r_worldentity); shaderstate.curtime = shaderstate.updatetime - (shaderstate.curentity->shaderTime + shader->remaptime); - shaderstate.curtexnums = texnums; + if (texnums) + shaderstate.curtexnums = texnums; + else if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; while (nummeshes--) { @@ -4316,21 +4346,27 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ if (shaderstate.curentity != &r_worldentity) GLBE_SelectEntity(&r_worldentity); shaderstate.curtime = shaderstate.updatetime - (shaderstate.curentity->shaderTime + shader->remaptime); - shaderstate.curtexnums = texnums; + if (texnums) + shaderstate.curtexnums = texnums; + else if (shader->numdefaulttextures) + shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures); + else + shaderstate.curtexnums = shader->defaulttextures; shaderstate.meshcount = nummeshes; shaderstate.meshes = meshlist; DrawMeshes(); } } -void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) +void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, unsigned int beflags) { shader->next = NULL; - BE_DrawMesh_List(shader, 1, &mesh, NULL, texnums, beflags); + BE_DrawMesh_List(shader, 1, &mesh, NULL, NULL, beflags); } void GLBE_SubmitBatch(batch_t *batch) { + shader_t *sh; shaderstate.curbatch = batch; if (batch->vbo) { @@ -4344,15 +4380,18 @@ void GLBE_SubmitBatch(batch_t *batch) return; } - shaderstate.curshader = batch->shader->remapto; + sh = batch->shader; + shaderstate.curshader = sh->remapto; shaderstate.flags = batch->flags; if (shaderstate.curentity != batch->ent) GLBE_SelectEntity(batch->ent); - shaderstate.curtime = shaderstate.updatetime - (shaderstate.curentity->shaderTime + batch->shader->remaptime); + shaderstate.curtime = shaderstate.updatetime - (shaderstate.curentity->shaderTime + sh->remaptime); if (batch->skin) shaderstate.curtexnums = batch->skin; + else if (sh->numdefaulttextures) + shaderstate.curtexnums = sh->defaulttextures + ((int)(sh->defaulttextures_fps * shaderstate.curtime) % sh->numdefaulttextures); else - shaderstate.curtexnums = &batch->shader->defaulttextures; + shaderstate.curtexnums = sh->defaulttextures; if (0) { diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index bcdbd4557..45d08b410 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -162,9 +162,9 @@ static void R_SetupBloomTextures(int w, int h) "map $upperoverlay\n" "}\n" "}\n"); - bloomfinal->defaulttextures.base = pingtex[0][0]; - bloomfinal->defaulttextures.loweroverlay = pingtex[0][1]; - bloomfinal->defaulttextures.upperoverlay = pingtex[0][2]; + bloomfinal->defaulttextures->base = pingtex[0][0]; + bloomfinal->defaulttextures->loweroverlay = pingtex[0][1]; + bloomfinal->defaulttextures->upperoverlay = pingtex[0][2]; } qboolean R_CanBloom(void) { diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index a9bc0b9f5..3d3e5e912 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -254,7 +254,7 @@ static void GL_Texturemode_Apply(GLenum targ, unsigned int flags) if (gl_anisotropy_factor) //0 means driver doesn't support { //only use anisotrophy when using linear any linear, because of drivers that forces linear sampling when anis is active (annoyingly this is allowed by the spec). - if ((min == GL_LINEAR || min == GL_LINEAR_MIPMAP_LINEAR || min == GL_LINEAR_MIPMAP_NEAREST) && mag == GL_LINEAR) + if ((min == GL_LINEAR_MIPMAP_LINEAR || min == GL_LINEAR_MIPMAP_NEAREST) && mag == GL_LINEAR) qglTexParameterf(targ, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy_factor); else qglTexParameterf(targ, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); @@ -327,10 +327,18 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips) //this is available in gles3 if (!gl_config.gles) { - if (targ != GL_TEXTURE_CUBE_MAP_ARB && (tex->flags & IF_MIPCAP)) + if (targ != GL_TEXTURE_CUBE_MAP_ARB) { - qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(mips->mipcount-1, gl_mipcap_min)); - qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(mips->mipcount-1, gl_mipcap_max)); + if (tex->flags & IF_MIPCAP) + { + qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(mips->mipcount-1, gl_mipcap_min)); + qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(mips->mipcount-1, gl_mipcap_max)); + } + else + { + qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, 0); + qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, mips->mipcount-1); + } } } diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 8fb9f6fbd..537182f41 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -384,10 +384,10 @@ static void Font_Flush(void) font_backmesh.numvertexes = font_foremesh.numvertexes; font_backmesh.istrifan = font_foremesh.istrifan; - BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, &fontplanes.backshader->defaulttextures, r2d_be_flags); + BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, r2d_be_flags); } - TEXASSIGN(fontplanes.shader->defaulttextures.base, font_texture); - BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, &fontplanes.shader->defaulttextures, r2d_be_flags); + TEXASSIGN(fontplanes.shader->defaulttextures->base, font_texture); + BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, r2d_be_flags); font_foremesh.numindexes = 0; font_foremesh.numvertexes = 0; } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index db41d1e14..9884a123e 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -3069,7 +3069,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) b->mesh[0] = &hm->skymesh; b->meshes = 1; b->buildmeshes = NULL; - b->skin = &b->shader->defaulttextures; + b->skin = NULL; b->texture = NULL; // vbo = b->vbo = hm->vbo[x+y*MAXSECTIONS]; b->vbo = NULL; @@ -5171,7 +5171,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) miptex_t *tx = W_GetMipTex(bt->shadername); if (tx) { - R_InitSky (&bt->shader->defaulttextures, bt->shadername, (qbyte*)tx + tx->offsets[0], tx->width, tx->height); + R_InitSky (bt->shader, bt->shadername, (qbyte*)tx + tx->offsets[0], tx->width, tx->height); BZ_Free(tx); } else @@ -5302,7 +5302,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) b->mesh = &bb->pmesh; b->meshes = 1; b->buildmeshes = NULL; - b->skin = &b->shader->defaulttextures; + b->skin = NULL; b->texture = NULL; b->vbo = &bb->vbo; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index a9463f690..0e316b5d4 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -37,6 +37,7 @@ cvar_t mod_loadentfiles = CVAR("sv_loadentfiles", "1"); cvar_t mod_external_vis = CVARD("mod_external_vis", "1", "Attempt to load .vis patches for quake maps, allowing transparent water to work properly."); cvar_t mod_warnmodels = CVARD("mod_warnmodels", "1", "Warn if any models failed to load. Set to 0 if your mod is likely to lack optional models (like its in development)."); //set to 0 for hexen2 and its otherwise-spammy-as-heck demo. cvar_t mod_litsprites = CVARD("mod_litsprites", "0", "If set to 1, sprites will be lit according to world lighting (including rtlights), like Tenebrae. Use EF_ADDITIVE or EF_FULLBRIGHT to make emissive sprites instead."); +cvar_t temp_lit2support = CVARD("temp_mod_lit2support", "0", "Set to 1 to enable lit2 support. This cvar will be removed once the format is finalised."); #ifdef SERVERONLY cvar_t gl_overbright, gl_specular, gl_load24bit, r_replacemodels, gl_miptexLevel, r_fb_bmodels; //all of these can/should default to 0 cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE); @@ -239,7 +240,7 @@ static void Mod_BlockTextureColour_f (void) continue; //happens on e1m2 if (!stricmp(tx->name, match)) - tx->shader->defaulttextures.base = Image_GetTexture(texname, NULL, IF_NOMIPMAP|IF_NEAREST, &rgba, NULL, 1, 1, TF_BGRA32); + tx->shader->defaulttextures->base = Image_GetTexture(texname, NULL, IF_NOMIPMAP|IF_NEAREST, &rgba, NULL, 1, 1, TF_BGRA32); } } } @@ -555,6 +556,7 @@ void Mod_Init (qboolean initial) Cvar_Register(&mod_warnmodels, "Graphical Nicaties"); Cvar_Register(&mod_litsprites, "Graphical Nicaties"); Cvar_Register(&mod_loadentfiles, NULL); + Cvar_Register(&temp_lit2support, NULL); Cmd_AddCommand("version_modelformats", Mod_PrintFormats_f); } @@ -1283,7 +1285,7 @@ void Mod_FinishTexture(texture_t *tx, const char *loadname) } if (!strncmp(tx->name, "sky", 3)) - R_InitSky (&tx->shader->defaulttextures, shadername, tx->mips[0], tx->width, tx->height); + R_InitSky (tx->shader, shadername, tx->mips[0], tx->width, tx->height); else { unsigned int maps = 0; @@ -1291,7 +1293,7 @@ void Mod_FinishTexture(texture_t *tx, const char *loadname) maps |= SHADER_HASDIFFUSE; if (r_fb_bmodels.ival) maps |= SHADER_HASFULLBRIGHT; - if (r_loadbumpmapping || (r_waterstyle.ival > 1 && *tx->name == '*')) + if (r_loadbumpmapping || (r_waterstyle.ival > 1 && *tx->name == '*') || tx->shader->defaulttextures->reflectcube) maps |= SHADER_HASNORMALMAP; if (gl_specular.ival) maps |= SHADER_HASGLOSS; @@ -1578,12 +1580,27 @@ void BuildLightMapGammaTable (float g, float c) } } +typedef struct +{ + unsigned int magic; //"QLIT" + unsigned int version; //2 + unsigned int numsurfs; + unsigned int lmsize; //samples, not bytes (same size as vanilla lighting lump in a q1 bsp). + + //uint lmoffsets[numsurfs]; //completely overrides the bsp lightmap info + //ushort lmextents[numsurfs*2]; //only to avoid precision issues. width+height pairs, actual lightmap sizes on disk (so +1). + //byte lmstyles[numsurfs*4]; //completely overrides the bsp lightmap info + //byte lmshifts[numsurfs]; //default is 4 (1<<4=16), for 1/16th lightmap-to-texel ratio + //byte litdata[lmsize*3]; //rgb data + //byte luxdata[lmsize*3]; //stn light dirs (unsigned bytes +} qlit2_t; + /* ================= Mod_LoadLighting ================= */ -void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe) +void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe, lightmapoverrides_t *overrides) { qboolean luxtmp = true; qboolean littmp = true; @@ -1628,6 +1645,145 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean return; #ifndef SERVERONLY + if (!litdata && r_loadlits.value) + { + char *litname; + char litnamemaps[MAX_QPATH]; + char litnamelits[MAX_QPATH]; + int depthmaps; + int depthlits; + size_t litsize; + qboolean inhibitvalidation = false; + + { + Q_strncpyz(litnamemaps, loadmodel->name, sizeof(litnamelits)); + COM_StripExtension(loadmodel->name, litnamemaps, sizeof(litnamemaps)); + COM_DefaultExtension(litnamemaps, ".lit", sizeof(litnamemaps)); + depthmaps = COM_FDepthFile(litnamemaps, false); + } + { + Q_strncpyz(litnamelits, "lits/", sizeof(litnamelits)); + COM_StripExtension(COM_SkipPath(loadmodel->name), litnamelits+5, sizeof(litnamelits) - 5); + Q_strncatz(litnamelits, ".lit", sizeof(litnamelits)); + depthlits = COM_FDepthFile(litnamelits, false); + } + + if (depthmaps <= depthlits) + litname = litnamemaps; //maps has priority over lits + else + litname = litnamelits; + + litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); + if (litdata) + { //validate it, if we loaded one. + if (litdata[0] != 'Q' || litdata[1] != 'L' || litdata[2] != 'I' || litdata[3] != 'T') + { + litdata = NULL; + Con_Printf("lit \"%s\" isn't a lit\n", litname); + } + else if (LittleLong(*(int *)&litdata[4]) == 1 && l->filelen && samples*3 != (litsize-8)) + { + litdata = NULL; + Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname); + } + else if (LittleLong(*(int *)&litdata[4]) == 1) + { + //header+version + litdata += 8; + } + else if (LittleLong(*(int *)&litdata[4]) == 2 && overrides) + { + qlit2_t *ql2 = (qlit2_t*)litdata; + unsigned int *offsets = (unsigned int*)(ql2+1); + unsigned short *extents = (unsigned short*)(offsets+ql2->numsurfs); + unsigned char *styles = (unsigned char*)(extents+ql2->numsurfs*2); + unsigned char *shifts = (unsigned char*)(styles+ql2->numsurfs*4); + if (!temp_lit2support.ival) + { + litdata = NULL; + Con_Printf("lit2 support is disabled, pending format finalisation.\n", litname); + } + else if (loadmodel->numsurfaces != ql2->numsurfs) + { + litdata = NULL; + Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname); + } + else + { + inhibitvalidation = true; + + //surface code needs to know the overrides. + overrides->offsets = offsets; + overrides->extents = extents; + overrides->styles = styles; + overrides->shifts = shifts; + + //we're now using this amount of data. + samples = ql2->lmsize; + + litdata = shifts+ql2->numsurfs; + if (r_deluxemapping.ival) + luxdata = litdata+samples*3; + } + } + else + { + Con_Printf("lit \"%s\" isn't version 1 or 2.\n", litname); + litdata = NULL; + } + } + + littmp = false; + if (!litdata) + { + int size; + /*FIXME: bspx support for extents+lmscale, may require style+offset lumps too, not sure what to do here*/ + litdata = Q1BSPX_FindLump("RGBLIGHTING", &size); + if (size != samples*3) + litdata = NULL; + littmp = true; + } + else if (!inhibitvalidation) + { + if (lumdata) + { + float prop; + int i; + qbyte *lum; + qbyte *lit; + + //now some cheat protection. + lum = lumdata; + lit = litdata; + + for (i = 0; i < samples; i++) //force it to the same intensity. (or less, depending on how you see it...) + { +#define m(a, b, c) (a>(b>c?b:c)?a:(b>c?b:c)) + prop = (float)m(lit[0], lit[1], lit[2]); + + if (!prop) + { + lit[0] = *lum; + lit[1] = *lum; + lit[2] = *lum; + } + else + { + prop = *lum / prop; + lit[0] *= prop; + lit[1] *= prop; + lit[2] *= prop; + } + + lum++; + lit+=3; + } + //end anti-cheat + } + } + } + + if (!luxdata && r_loadlits.ival && r_deluxemapping.ival) { //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous. char luxname[MAX_QPATH]; @@ -1690,104 +1846,6 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } } } - - if (!litdata && r_loadlits.value) - { - char *litname; - char litnamemaps[MAX_QPATH]; - char litnamelits[MAX_QPATH]; - int depthmaps; - int depthlits; - size_t litsize; - - { - Q_strncpyz(litnamemaps, loadmodel->name, sizeof(litnamelits)); - COM_StripExtension(loadmodel->name, litnamemaps, sizeof(litnamemaps)); - COM_DefaultExtension(litnamemaps, ".lit", sizeof(litnamemaps)); - depthmaps = COM_FDepthFile(litnamemaps, false); - } - { - Q_strncpyz(litnamelits, "lits/", sizeof(litnamelits)); - COM_StripExtension(COM_SkipPath(loadmodel->name), litnamelits+5, sizeof(litnamelits) - 5); - Q_strncatz(litnamelits, ".lit", sizeof(litnamelits)); - depthlits = COM_FDepthFile(litnamelits, false); - } - - if (depthmaps <= depthlits) - litname = litnamemaps; //maps has priority over lits - else - litname = litnamelits; - - litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); - if (litdata) - { //validate it, if we loaded one. - if (litdata[0] != 'Q' || litdata[1] != 'L' || litdata[2] != 'I' || litdata[3] != 'T') - { - litdata = NULL; - Con_Printf("lit \"%s\" isn't a lit\n", litname); - } - else if (LittleLong(*(int *)&litdata[4]) == 1 && l->filelen && samples*3 != (litsize-8)) - { - litdata = NULL; - Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname); - } - else if (LittleLong(*(int *)&litdata[4]) != 1) - { - Con_Printf("lit \"%s\" isn't version 1.\n", litname); - litdata = NULL; - } - } - - littmp = false; - if (!litdata) - { - int size; - litdata = Q1BSPX_FindLump("RGBLIGHTING", &size); - if (size != samples*3) - litdata = NULL; - littmp = true; - } - else - { - if (lumdata) - { - float prop; - int i; - qbyte *lum; - qbyte *lit; - - litdata += 8; - - //now some cheat protection. - lum = lumdata; - lit = litdata; - - for (i = 0; i < samples; i++) //force it to the same intensity. (or less, depending on how you see it...) - { -#define m(a, b, c) (a>(b>c?b:c)?a:(b>c?b:c)) - prop = (float)m(lit[0], lit[1], lit[2]); - - if (!prop) - { - lit[0] = *lum; - lit[1] = *lum; - lit[2] = *lum; - } - else - { - prop = *lum / prop; - lit[0] *= prop; - lit[1] *= prop; - lit[2] *= prop; - } - - lum++; - lit+=3; - } - //end anti-cheat - } - } - } #endif #ifdef RUNTIMELIGHTING @@ -1865,6 +1923,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } /*apply lightmap gamma to the entire lightmap*/ + loadmodel->lightdatasize = samples; out = loadmodel->lightdata; if (interleaveddeluxe) { @@ -2302,17 +2361,21 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s); Mod_LoadFaces ================= */ -qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm) +qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *lightlump, qboolean lm) { dsface_t *ins; dlface_t *inl; msurface_t *out; int count, surfnum; int i, planenum, side; - int tn, lofs; + int tn; + unsigned int lofs, lend; unsigned short lmshift, lmscale; char buf[64]; + lightmapoverrides_t overrides; + + memset(&overrides, 0, sizeof(overrides)); lmscale = atoi(Mod_ParseWorldspawnKey(loadmodel->entities, "lightmap_scale", buf, sizeof(buf))); if (!lmscale) @@ -2350,6 +2413,9 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean // *meshlist = ZG_Malloc(&loadmodel->memgroup, count*sizeof(**meshlist)); loadmodel->surfaces = out; loadmodel->numsurfaces = count; + + Mod_LoadLighting (loadmodel, mod_base, lightlump, false, &overrides); + for ( surfnum=0 ; surfnumfirstedge = LittleLong(ins->firstedge); out->numedges = LittleShort(ins->numedges); tn = LittleShort (ins->texinfo); - for (i=0 ; istyles[i] = ins->styles[i]; lofs = LittleLong(ins->lightofs); ins++; @@ -2392,13 +2458,22 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } out->texinfo = loadmodel->texinfo + tn; - out->lmshift = lmshift; + if (overrides.shifts) + out->lmshift = overrides.shifts[surfnum]; + else + out->lmshift = lmshift; + if (overrides.offsets) + lofs = overrides.offsets[surfnum]; + if (overrides.styles) + for (i=0 ; istyles[i] = overrides.styles[surfnum*4+i]; CalcSurfaceExtents (loadmodel, out); - if (lofs == -1) - out->samples = NULL; - else if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife) - out->samples = loadmodel->lightdata + lofs*3; + if (lofs != (unsigned int)-1 && (loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife) + lofs *= 3; + lend = lofs+(out->extents[0]+1)*(out->extents[1]+1); + if (lofs > loadmodel->lightdatasize || lend < lofs) + out->samples = NULL; //should includes -1 else out->samples = loadmodel->lightdata + lofs; @@ -2447,7 +2522,7 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } #ifndef SERVERONLY -void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, void *cookie) +void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie) { unsigned int vertidx; int i, lindex; @@ -2456,6 +2531,7 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, void *cookie) float *vec; float s, t, d; int sty; + int w,h; //output the mesh's indicies for (i=0 ; inumvertexes-2 ; i++) @@ -2485,8 +2561,18 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, void *cookie) t = DotProduct (vec, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; VectorCopy (vec, mesh->xyz_array[i]); - mesh->st_array[i][0] = s/surf->texinfo->texture->width; - mesh->st_array[i][1] = t/surf->texinfo->texture->height; + +/* if (R_GetShaderSizes(surf->texinfo->texture->shader, &w, &h, false) > 0) + { + mesh->st_array[i][0] = s/w; + mesh->st_array[i][1] = t/h; + } + else +*/ + { + mesh->st_array[i][0] = s/surf->texinfo->texture->width; + mesh->st_array[i][1] = t/surf->texinfo->texture->height; + } if (gl_lightmap_average.ival) { @@ -4433,9 +4519,6 @@ qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize) { TRACE(("Loading Textures\n")); noerrors = noerrors && Mod_LoadTextures (mod, mod_base, &header->lumps[LUMP_TEXTURES]); - TRACE(("Loading Lighting\n")); - if (noerrors) - Mod_LoadLighting (mod, mod_base, &header->lumps[LUMP_LIGHTING], false); } TRACE(("Loading Submodels\n")); noerrors = noerrors && Mod_LoadSubmodels (mod, mod_base, &header->lumps[LUMP_MODELS]); @@ -4453,7 +4536,7 @@ qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize) TRACE(("Loading Texinfo\n")); noerrors = noerrors && Mod_LoadTexinfo (mod, mod_base, &header->lumps[LUMP_TEXINFO]); TRACE(("Loading Faces\n")); - noerrors = noerrors && Mod_LoadFaces (mod, mod_base, &header->lumps[LUMP_FACES], longm); + noerrors = noerrors && Mod_LoadFaces (mod, mod_base, &header->lumps[LUMP_FACES], &header->lumps[LUMP_LIGHTING], longm); } if (!isDedicated) { @@ -4678,7 +4761,7 @@ void Mod_LoadSpriteFrameShader(model_t *spr, int frame, int subframe, mspritefra else shadertext = SPRITE_SHADER_MAIN SPRITE_SHADER_UNLIT SPRITE_SHADER_FOOTER; frameinfo->shader = R_RegisterShader(name, SUF_NONE, shadertext); - frameinfo->shader->defaulttextures.base = frameinfo->image; + frameinfo->shader->defaulttextures->base = frameinfo->image; frameinfo->shader->width = frameinfo->right-frameinfo->left; frameinfo->shader->height = frameinfo->up-frameinfo->down; #endif diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 96372ec2d..2c87c6f92 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -929,6 +929,7 @@ typedef struct model_s void *vis; qbyte *lightdata; qbyte *deluxdata; + unsigned lightdatasize; q3lightgridinfo_t *lightgrid; mfog_t *fogs; int numfogs; diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index 9bc2b466b..21ce2f457 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -197,5 +197,5 @@ void R_NetgraphInit(void) "}\n" "}\n" ); - netgraphshader->defaulttextures.base = netgraphtexture; + netgraphshader->defaulttextures->base = netgraphtexture; } diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 5d06b9cff..cbf7956df 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -408,7 +408,7 @@ void R_RenderDlights (void) if (!R_BuildDlightMesh (l, intensity, cscale, coronastyle) && !coronastyle) AddLightBlend (l->color[0], l->color[1], l->color[2], l->radius * 0.0003); else - BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, (coronastyle?BEF_FORCENODEPTH|BEF_FORCEADDITIVE:0)|beflags); + BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, (coronastyle?BEF_FORCENODEPTH|BEF_FORCEADDITIVE:0)|beflags); } } @@ -481,7 +481,7 @@ void R_GenDlightBatches(batch_t *batches[]) b->mesh = NULL; b->firstmesh = 0; b->meshes = 1; - b->skin = &lpplight_shader->defaulttextures; + b->skin = NULL; b->texture = NULL; b->shader = lpplight_shader; for (j = 0; j < MAXRLIGHTMAPS; j++) diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 155568136..175611d26 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -122,8 +122,8 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) "}\n" "}\n" ); - scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp; - scenepp_waterwarp->defaulttextures.loweroverlay = scenepp_texture_edge; + scenepp_waterwarp->defaulttextures->upperoverlay = scenepp_texture_warp; + scenepp_waterwarp->defaulttextures->loweroverlay = scenepp_texture_edge; } } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 6c3e83876..8a263b73d 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -236,16 +236,6 @@ texid_t GenerateNormalisationCubeMap(void) texid_t normalisationCubeMap; #endif -/* -=============== -R_Init -=============== -*/ -void GLR_ReInit (void) -{ - R_NetgraphInit(); -} - #if 0 typedef struct { @@ -473,8 +463,6 @@ void GLR_Init (void) Cmd_AddCommand ("timerefresh", GLR_TimeRefresh_f); // Cmd_AddCommand ("makewad", R_MakeTexWad_f); - - GLR_ReInit(); } /* diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index ed50e57f1..36b97d8d5 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -41,6 +41,7 @@ sh_config_t sh_config; //cvars that affect shader generation cvar_t r_vertexlight = CVARFD("r_vertexlight", "0", CVAR_SHADERSYSTEM, "Hack loaded shaders to remove detail pass and lightmap sampling for faster rendering."); +cvar_t r_forceprogramify = CVARAFD("r_forceprogramify", "0", "dpcompat_makeshitup", CVAR_SHADERSYSTEM, "Reduce the shader to a single texture, and then make stuff up about its mother. The resulting fist fight results in more colour when you shine a light upon its face.\nSet to 2 to ignore 'depthfunc equal' and 'tcmod scale' in order to tolerate bizzare shaders made for a bizzare engine."); extern cvar_t r_glsl_offsetmapping_reliefmapping; extern cvar_t r_deluxemapping; extern cvar_t r_fastturb, r_fastsky, r_skyboxname, r_softwarebanding; @@ -633,13 +634,15 @@ static int Shader_SetImageFlags(shader_t *shader, shaderpass_t *pass, char **nam { *name+=9; flags|= IF_NEAREST; - pass->flags |= SHADER_PASS_NEAREST; + if (pass) + pass->flags |= SHADER_PASS_NEAREST; } else if (!Q_strnicmp(*name, "$linear:", 8)) { *name+=8; flags|= IF_LINEAR; - pass->flags |= SHADER_PASS_LINEAR; + if (pass) + pass->flags |= SHADER_PASS_LINEAR; } else break; @@ -651,6 +654,7 @@ static int Shader_SetImageFlags(shader_t *shader, shaderpass_t *pass, char **nam flags |= IF_NOMIPMAP; if (shader->flags & SHADER_NOPICMIP) flags |= IF_NOPICMIP; + flags |= IF_MIPCAP; return flags; } @@ -685,6 +689,7 @@ texid_t R_LoadColourmapImage(void) static texid_t Shader_FindImage ( char *name, int flags ) { + extern texid_t missing_texture_normal; if (parsestate.mode == SPM_DOOM3) { if (!Q_stricmp (name, "_default")) @@ -701,6 +706,13 @@ static texid_t Shader_FindImage ( char *name, int flags ) { if (!Q_stricmp (name, "$whiteimage")) return r_whiteimage; + if (!Q_stricmp (name, "$blackimage")) + { + int wibuf[16] = {0}; + return R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); + } + if (!Q_stricmp (name, "$identitynormal")) + return missing_texture_normal; if (!Q_stricmp (name, "$colourmap")) return R_LoadColourmapImage(); } @@ -954,7 +966,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip "#define BUMP\n", "#define FULLBRIGHT\n", "#define UPPERLOWER\n", - "#define DELUXE\n", + "#define REFLECTCUBEMASK\n", "#define SKELETAL\n", "#define FOG\n", "#define FRAMEBLEND\n", @@ -1095,6 +1107,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip { //we 'recognise' ones that are force-defined, despite not being actual permutations. if (strncmp("SPECULAR", script, end - script)) + if (strncmp("DELUXE", script, end - script)) if (strncmp("OFFSETMAPPING", script, end - script)) if (strncmp("RELIEFMAPPING", script, end - script)) Con_DPrintf("Unknown pemutation in glsl program %s\n", name); @@ -1289,6 +1302,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip if (r_glsl_offsetmapping_reliefmapping.ival && (p & PERMUTATION_BUMPMAP)) permutationdefines[pn++] = "#define RELIEFMAPPING\n"; } + + if (r_deluxemapping.ival) //fixme: should be per-model really + permutationdefines[pn++] = "#define DELUXE\n"; } permutationdefines[pn++] = NULL; @@ -1903,41 +1919,54 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p #endif } +static void Shader_ReflectCube(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->reflectcube = Shader_FindImage(token, flags|IF_CUBEMAP); +} +static void Shader_ReflectMask(shader_t *shader, shaderpass_t *pass, char **ptr) +{ + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->reflectmask = Shader_FindImage(token, flags); +} + 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); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->base = Shader_FindImage(token, flags); } static void Shader_SpecularMap(shader_t *shader, shaderpass_t *pass, char **ptr) { - char *token; - token = Shader_ParseString(ptr); - shader->defaulttextures.specular = R_LoadHiResTexture(token, NULL, 0); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->specular = Shader_FindImage(token, flags); } -static void Shader_BumpMap(shader_t *shader, shaderpass_t *pass, char **ptr) +static void Shader_NormalMap(shader_t *shader, shaderpass_t *pass, char **ptr) { - char *token; - token = Shader_ParseString(ptr); - shader->defaulttextures.bump = R_LoadHiResTexture(token, NULL, 0); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->bump = Shader_FindImage(token, flags); } static void Shader_FullbrightMap(shader_t *shader, shaderpass_t *pass, char **ptr) { - char *token; - token = Shader_ParseString(ptr); - shader->defaulttextures.fullbright = R_LoadHiResTexture(token, NULL, 0); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->fullbright = Shader_FindImage(token, flags); } static void Shader_UpperMap(shader_t *shader, shaderpass_t *pass, char **ptr) { - char *token; - token = Shader_ParseString(ptr); - shader->defaulttextures.upperoverlay = R_LoadHiResTexture(token, NULL, 0); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->upperoverlay = Shader_FindImage(token, flags); } static void Shader_LowerMap(shader_t *shader, shaderpass_t *pass, char **ptr) { - char *token; - token = Shader_ParseString(ptr); - shader->defaulttextures.loweroverlay = R_LoadHiResTexture(token, NULL, 0); + char *token = Shader_ParseString(ptr); + unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); + shader->defaulttextures->loweroverlay = Shader_FindImage(token, flags); } static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *tname); @@ -2074,16 +2103,21 @@ static shaderkey_t shaderkeys[] = {"bemode", Shader_BEMode, "fte"}, + {"diffusemap", Shader_DiffuseMap, "fte"}, + {"normalmap", Shader_NormalMap, "fte"}, + {"specularmap", Shader_SpecularMap, "fte"}, + {"fullbrightmap", Shader_FullbrightMap, "fte"}, + {"uppermap", Shader_UpperMap, "fte"}, + {"lowermap", Shader_LowerMap, "fte"}, + {"reflectmask", Shader_ReflectMask, "fte"}, + //dp compat {"camera", Shader_DP_Camera, "dp"}, + {"reflectcube", Shader_ReflectCube, "dp"}, /*doom3 compat*/ {"diffusemap", Shader_DiffuseMap, "doom3"}, //macro for "{\nstage diffusemap\nmap \n}" - {"bumpmap", Shader_BumpMap, "doom3"}, //macro for "{\nstage bumpmap\nmap \n}" - {"specularmap", Shader_SpecularMap, "doom3"},//macro for "{\nstage specularmap\nmap \n}" - {"fullbrightmap", Shader_FullbrightMap, "doom3"},//macro for "{\nstage specularmap\nmap \n}" - {"uppermap", Shader_UpperMap, "doom3"},//macro for "{\nstage specularmap\nmap \n}" - {"lowermap", Shader_LowerMap, "doom3"},//macro for "{\nstage specularmap\nmap \n}" + {"bumpmap", Shader_NormalMap, "doom3"}, //macro for "{\nstage bumpmap\nmap \n}" {"discrete", NULL, "doom3"}, {"nonsolid", NULL, "doom3"}, {"noimpact", NULL, "doom3"}, @@ -2250,8 +2284,8 @@ static void Shaderpass_Map (shader_t *shader, shaderpass_t *pass, char **ptr) if (pass->tcgen == TC_GEN_UNSPECIFIED) pass->tcgen = TC_GEN_BASE; - if (!*shader->mapname && *token != '$' && pass->tcgen == TC_GEN_BASE) - Q_strncpyz(shader->mapname, token, sizeof(shader->mapname)); + if (!*shader->defaulttextures->mapname && *token != '$' && pass->tcgen == TC_GEN_BASE) + Q_strncpyz(shader->defaulttextures->mapname, token, sizeof(shader->defaulttextures->mapname)); pass->anim_frames[0] = Shader_FindImage (token, flags); } } @@ -2261,6 +2295,7 @@ static void Shaderpass_AnimMap (shader_t *shader, shaderpass_t *pass, char **ptr int flags; char *token; texid_t image; + qboolean isdiffuse = false; flags = Shader_SetImageFlags (shader, pass, NULL); @@ -2279,10 +2314,27 @@ static void Shaderpass_AnimMap (shader_t *shader, shaderpass_t *pass, char **ptr break; } + if (!pass->anim_numframes && !*shader->defaulttextures->mapname && *token != '$' && pass->tcgen == TC_GEN_BASE) + { + isdiffuse = true; + shader->defaulttextures_fps = pass->anim_fps; + } + if (pass->anim_numframes < SHADER_MAX_ANIMFRAMES) { image = Shader_FindImage (token, flags); + if (isdiffuse) + { + if (shader->numdefaulttextures < pass->anim_numframes+1) + { + int newmax = pass->anim_numframes+1; + shader->defaulttextures = BZ_Realloc(shader->defaulttextures, sizeof(*shader->defaulttextures) * (newmax)); + memset(shader->defaulttextures+shader->numdefaulttextures, 0, sizeof(*shader->defaulttextures) * (newmax-shader->numdefaulttextures)); + shader->numdefaulttextures = newmax; + } + Q_strncpyz(shader->defaulttextures[pass->anim_numframes].mapname, token, sizeof(shader->defaulttextures[pass->anim_numframes].mapname)); + } if (!TEXVALID(image)) { pass->anim_frames[pass->anim_numframes++] = missing_texture; @@ -2975,7 +3027,8 @@ void Shader_Free (shader_t *shader) } shader->uses = 0; - memset(&shader->defaulttextures, 0, sizeof(shader->defaulttextures)); + Z_Free(shader->defaulttextures); + shader->defaulttextures = NULL; } @@ -3188,12 +3241,15 @@ void Shader_Reset(shader_t *s) int uses = s->uses; shader_gen_t *defaultgen = s->generator; char *genargs = s->genargs; - texnums_t dt = s->defaulttextures; + texnums_t *dt = s->defaulttextures; + int dtcount = s->numdefaulttextures; + float dtrate = s->defaulttextures_fps; //FIXME! int w = s->width; int h = s->height; unsigned int uf = s->usageflags; Q_strncpyz(name, s->name, sizeof(name)); s->genargs = NULL; + s->defaulttextures = NULL; Shader_Free(s); memset(s, 0, sizeof(*s)); @@ -3204,6 +3260,8 @@ void Shader_Reset(shader_t *s) s->width = w; s->height = h; s->defaulttextures = dt; + s->numdefaulttextures = dtcount; + s->defaulttextures_fps = dtrate; s->generator = defaultgen; s->genargs = genargs; s->usageflags = uf; @@ -3407,18 +3465,18 @@ void Shader_Readpass (shader_t *shader, char **ptr) { case ST_DIFFUSEMAP: if (pass->texgen == T_GEN_SINGLEMAP) - shader->defaulttextures.base = pass->anim_frames[0]; + shader->defaulttextures->base = pass->anim_frames[0]; break; case ST_AMBIENT: break; case ST_BUMPMAP: if (pass->texgen == T_GEN_SINGLEMAP) - shader->defaulttextures.bump = pass->anim_frames[0]; + shader->defaulttextures->bump = pass->anim_frames[0]; ignore = true; //fixme: scrolling etc may be important. but we're not doom3. break; case ST_SPECULARMAP: if (pass->texgen == T_GEN_SINGLEMAP) - shader->defaulttextures.specular = pass->anim_frames[0]; + shader->defaulttextures->specular = pass->anim_frames[0]; ignore = true; //fixme: scrolling etc may be important. but we're not doom3. break; } @@ -3673,9 +3731,12 @@ void Shader_Programify (shader_t *s) mask = Shader_AlphaMaskProgArgs(s); s->prog = Shader_FindGeneric(va("%s%s", prog, mask), qrenderer); - s->numpasses = 0; - s->passes[s->numpasses++].texgen = T_GEN_DIFFUSE; - s->flags |= SHADER_HASDIFFUSE; + if (s->prog) + { + s->numpasses = 0; + s->passes[s->numpasses++].texgen = T_GEN_DIFFUSE; + s->flags |= SHADER_HASDIFFUSE; + } } void Shader_Finish (shader_t *s) @@ -3733,7 +3794,7 @@ void Shader_Finish (shader_t *s) pass = &s->passes[s->numpasses++]; pass = &s->passes[0]; pass->tcgen = TC_GEN_BASE; - if (TEXVALID(s->defaulttextures.base)) + if (TEXVALID(s->defaulttextures->base)) pass->texgen = T_GEN_DIFFUSE; else { @@ -3859,17 +3920,17 @@ void Shader_Finish (shader_t *s) done:; //if we've no specular map, try and find whatever the q3 syntax said. hopefully it'll be compatible... - if (!TEXVALID(s->defaulttextures.specular)) + if (!TEXVALID(s->defaulttextures->specular)) { for (pass = s->passes, i = 0; i < s->numpasses; i++, pass++) { if (pass->alphagen == ALPHA_GEN_SPECULAR) if (pass->texgen == T_GEN_ANIMMAP || pass->texgen == T_GEN_SINGLEMAP) - s->defaulttextures.specular = pass->anim_frames[0]; + s->defaulttextures->specular = pass->anim_frames[0]; } } - if (!TEXVALID(s->defaulttextures.base)) + if (!TEXVALID(s->defaulttextures->base)) { shaderpass_t *best = NULL; int bestweight = 9999999; @@ -3903,11 +3964,11 @@ done:; if (best->texgen == T_GEN_ANIMMAP || best->texgen == T_GEN_SINGLEMAP) { if (best->anim_frames[0] && *best->anim_frames[0]->ident != '$') - s->defaulttextures.base = best->anim_frames[0]; + s->defaulttextures->base = best->anim_frames[0]; } #ifndef NOMEDIA else if (pass->texgen == T_GEN_VIDEOMAP && pass->cin) - s->defaulttextures.base = Media_UpdateForShader(best->cin); + s->defaulttextures->base = Media_UpdateForShader(best->cin); #endif } } @@ -3948,7 +4009,7 @@ done:; Shader_SetBlendmode (pass); if (pass->blendmode == PBM_ADD) - s->defaulttextures.fullbright = pass->anim_frames[0]; + s->defaulttextures->fullbright = pass->anim_frames[0]; } if (!(s->flags & SHADER_SKY ) && !s->sort) @@ -4035,8 +4096,16 @@ done:; "}\n"); } - if (!s->prog && sh_config.progs_required) + if (!s->prog && (sh_config.progs_required || (sh_config.progs_supported && r_forceprogramify.ival))) + { Shader_Programify(s); + if (r_forceprogramify.ival >= 2) + { + if (s->passes[0].numtcmods == 1 && s->passes[0].tcmods[0].type == SHADER_TCMOD_SCALE) + s->passes[0].numtcmods = 0; //DP sucks and doesn't use normalized texture coords *if* there's a shader specified. so lets ignore any extra scaling that this imposes. + s->passes[0].shaderbits &= ~SBITS_MISC_DEPTHEQUALONLY; //DP ignores this too. + } + } if (s->prog) { @@ -4055,6 +4124,8 @@ done:; {T_GEN_PALETTED, SHADER_HASPALETTED}, {T_GEN_SHADOWMAP, 0}, {T_GEN_LIGHTCUBEMAP, 0}, + {T_GEN_REFLECTCUBE, 0}, + {T_GEN_REFLECTMASK, 0}, // {T_GEN_REFLECTION, SHADER_HASREFLECT}, // {T_GEN_REFRACTION, SHADER_HASREFRACT}, // {T_GEN_REFRACTIONDEPTH, SHADER_HASREFRACTDEPTH}, @@ -4062,18 +4133,36 @@ done:; {T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, {T_GEN_DELUXMAP, 0}, }; + + cin_t *cin = R_ShaderGetCinematic(s); + //if the glsl doesn't specify all samplers, just trim them. s->numpasses = s->prog->numsamplers; + if (cin && R_ShaderGetCinematic(s) == cin) + cin = NULL; + //if the glsl has specific textures listed, be sure to provide a pass for them. for (i = 0; i < sizeof(defaulttgen)/sizeof(defaulttgen[0]); i++) { if (s->prog->defaulttextures & (1u<numpasses >= SHADER_PASS_MAX) + break; //panic... s->passes[s->numpasses].flags &= ~SHADER_PASS_DEPTHCMP; if (defaulttgen[i].gen == T_GEN_SHADOWMAP) s->passes[s->numpasses].flags |= SHADER_PASS_DEPTHCMP; - s->passes[s->numpasses].texgen = defaulttgen[i].gen; + if (!i && cin) + { + s->passes[s->numpasses].texgen = T_GEN_VIDEOMAP; + s->passes[s->numpasses].cin = cin; + cin = NULL; + } + else + { + s->passes[s->numpasses].texgen = defaulttgen[i].gen; + s->passes[s->numpasses].cin = NULL; + } s->numpasses++; s->flags |= defaulttgen[i].flags; } @@ -4082,9 +4171,12 @@ done:; //must have at least one texture. if (!s->numpasses) { - s->passes[0].texgen = T_GEN_DIFFUSE; + s->passes[0].texgen = cin?T_GEN_VIDEOMAP:T_GEN_DIFFUSE; + s->passes[0].cin = cin; s->numpasses = 1; } + else if (cin) + Media_ShutdownCin(cin); s->passes->numMergedPasses = s->numpasses; } } @@ -4151,11 +4243,14 @@ void Shader_UpdateRegistration (void) } */ void Shader_DefaultSkin(const char *shortname, shader_t *s, const void *args); -void QDECL R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) +void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader) { char *h; char imagename[MAX_QPATH]; + char mapname[MAX_QPATH]; char *subpath = NULL; + texnums_t *tex; + unsigned int a, aframes; unsigned int imageflags = 0; strcpy(imagename, shader->name); h = strchr(imagename, '#'); @@ -4171,94 +4266,131 @@ void QDECL R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) if (shader->generator == Shader_DefaultSkin) subpath = shader->genargs; - if (!tn) - tn = &shader->defaulttextures; - if (!TEXVALID(shader->defaulttextures.base)) + tex = shader->defaulttextures; + aframes = max(1, shader->numdefaulttextures); + //if any were specified explicitly, replicate that into all. + //this means animmap can be used, with any explicit textures overriding all. + if (!shader->numdefaulttextures && src) { - /*dlights/realtime lighting needs some stuff*/ - if (!TEXVALID(tn->base) && *shader->mapname)// && (shader->flags & SHADER_HASDIFFUSE)) - tn->base = R_LoadHiResTexture(shader->mapname, NULL, 0); - if (!TEXVALID(tn->base)) - tn->base = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA); - - TEXASSIGN(shader->defaulttextures.base, tn->base); + //only do this if there wasn't an animmap thing to break everything. + if (!TEXVALID(tex->base)) + tex->base = src->base; + if (!TEXVALID(tex->bump)) + tex->bump = src->bump; + if (!TEXVALID(tex->fullbright)) + tex->fullbright = src->fullbright; + if (!TEXVALID(tex->specular)) + tex->specular = src->specular; + if (!TEXVALID(tex->loweroverlay)) + tex->loweroverlay = src->loweroverlay; + if (!TEXVALID(tex->upperoverlay)) + tex->upperoverlay = src->upperoverlay; + if (!TEXVALID(tex->reflectmask)) + tex->reflectmask = src->reflectmask; + if (!TEXVALID(tex->reflectcube)) + tex->reflectcube = src->reflectcube; } - - if (!TEXVALID(shader->defaulttextures.paletted)) + for (a = 1; a < aframes; a++) { - /*dlights/realtime lighting needs some stuff*/ -// if (!TEXVALID(tn->paletted) && *shader->mapname)// && (shader->flags & SHADER_HASDIFFUSE)) -// tn->paletted = R_LoadHiResTexture(shader->mapname, NULL, 0); -// if (!TEXVALID(tn->paletted)) -// tn->paletted = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA); - - TEXASSIGN(shader->defaulttextures.paletted, tn->paletted); + if (!TEXVALID(tex[a].base)) + tex[a].base = tex[0].base; + if (!TEXVALID(tex[a].bump)) + tex[a].bump = tex[0].bump; + if (!TEXVALID(tex[a].fullbright)) + tex[a].fullbright = tex[0].fullbright; + if (!TEXVALID(tex[a].specular)) + tex[a].specular = tex[0].specular; + if (!TEXVALID(tex[a].loweroverlay)) + tex[a].loweroverlay = tex[0].loweroverlay; + if (!TEXVALID(tex[a].upperoverlay)) + tex[a].upperoverlay = tex[0].upperoverlay; + if (!TEXVALID(tex[a].reflectmask)) + tex[a].reflectmask = tex[0].reflectmask; + if (!TEXVALID(tex[a].reflectcube)) + tex[a].reflectcube = tex[0].reflectcube; } - - imageflags |= IF_LOWPRIORITY; - - COM_StripExtension(imagename, imagename, sizeof(imagename)); - - if (!TEXVALID(shader->defaulttextures.bump)) + for (a = 0; a < aframes; a++, tex++) { - if (r_loadbumpmapping || (shader->flags & SHADER_HASNORMALMAP)) + COM_StripExtension(tex->mapname, mapname, sizeof(mapname)); + + if (!TEXVALID(tex->base)) { - if (!TEXVALID(tn->bump) && *shader->mapname && (shader->flags & SHADER_HASNORMALMAP)) - tn->bump = R_LoadHiResTexture(va("%s_norm", shader->mapname), NULL, imageflags|IF_TRYBUMP); - if (!TEXVALID(tn->bump)) - tn->bump = R_LoadHiResTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP); + /*dlights/realtime lighting needs some stuff*/ + if (!TEXVALID(tex->base) && *tex->mapname)// && (shader->flags & SHADER_HASDIFFUSE)) + tex->base = R_LoadHiResTexture(tex->mapname, NULL, 0); + if (!TEXVALID(tex->base)) + tex->base = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA); } - TEXASSIGN(shader->defaulttextures.bump, tn->bump); - } - if (!TEXVALID(shader->defaulttextures.loweroverlay)) - { - if (shader->flags & SHADER_HASTOPBOTTOM) + if (!TEXVALID(tex->paletted)) { - if (!TEXVALID(tn->loweroverlay) && *shader->mapname) - tn->loweroverlay = R_LoadHiResTexture(va("%s_pants", shader->mapname), NULL, imageflags); - if (!TEXVALID(tn->loweroverlay)) - tn->loweroverlay = R_LoadHiResTexture(va("%s_pants", imagename), subpath, imageflags); /*how rude*/ + /*dlights/realtime lighting needs some stuff*/ + // if (!TEXVALID(tn->paletted) && *shader->mapname)// && (shader->flags & SHADER_HASDIFFUSE)) + // tn->paletted = R_LoadHiResTexture(shader->mapname, NULL, 0); + // if (!TEXVALID(tn->paletted)) + // tn->paletted = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA); } - TEXASSIGN(shader->defaulttextures.loweroverlay, tn->loweroverlay); - } - if (!TEXVALID(shader->defaulttextures.upperoverlay)) - { - if (shader->flags & SHADER_HASTOPBOTTOM) - { - if (!TEXVALID(tn->upperoverlay) && *shader->mapname) - tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->mapname), NULL, imageflags); - if (!TEXVALID(tn->upperoverlay)) - tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", imagename), subpath, imageflags); - } - TEXASSIGN(shader->defaulttextures.upperoverlay, tn->upperoverlay); - } + imageflags |= IF_LOWPRIORITY; - if (!TEXVALID(shader->defaulttextures.specular)) - { - extern cvar_t gl_specular; - if ((shader->flags & SHADER_HASGLOSS) && gl_specular.value && gl_load24bit.value) - { - if (!TEXVALID(tn->specular) && *shader->mapname) - tn->specular = R_LoadHiResTexture(va("%s_gloss", shader->mapname), NULL, imageflags); - if (!TEXVALID(tn->specular)) - tn->specular = R_LoadHiResTexture(va("%s_gloss", imagename), subpath, imageflags); - } - TEXASSIGN(shader->defaulttextures.specular, tn->specular); - } + COM_StripExtension(imagename, imagename, sizeof(imagename)); - if (!TEXVALID(shader->defaulttextures.fullbright)) - { - extern cvar_t r_fb_bmodels; - if ((shader->flags & SHADER_HASFULLBRIGHT) && r_fb_bmodels.value && gl_load24bit.value) + if (!TEXVALID(tex->bump)) { - if (!TEXVALID(tn->fullbright) && *shader->mapname) - tn->fullbright = R_LoadHiResTexture(va("%s_luma", shader->mapname), NULL, imageflags); - if (!TEXVALID(tn->fullbright)) - tn->fullbright = R_LoadHiResTexture(va("%s_luma", imagename), subpath, imageflags); + if (r_loadbumpmapping || (shader->flags & SHADER_HASNORMALMAP)) + { + if (!TEXVALID(tex->bump) && *mapname && (shader->flags & SHADER_HASNORMALMAP)) + tex->bump = R_LoadHiResTexture(va("%s_norm", mapname), NULL, imageflags|IF_TRYBUMP); + if (!TEXVALID(tex->bump)) + tex->bump = R_LoadHiResTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP); + } + } + + if (!TEXVALID(tex->loweroverlay)) + { + if (shader->flags & SHADER_HASTOPBOTTOM) + { + if (!TEXVALID(tex->loweroverlay) && *mapname) + tex->loweroverlay = R_LoadHiResTexture(va("%s_pants", mapname), NULL, imageflags); + if (!TEXVALID(tex->loweroverlay)) + tex->loweroverlay = R_LoadHiResTexture(va("%s_pants", imagename), subpath, imageflags); /*how rude*/ + } + } + + if (!TEXVALID(tex->upperoverlay)) + { + if (shader->flags & SHADER_HASTOPBOTTOM) + { + if (!TEXVALID(tex->upperoverlay) && *mapname) + tex->upperoverlay = R_LoadHiResTexture(va("%s_shirt", mapname), NULL, imageflags); + if (!TEXVALID(tex->upperoverlay)) + tex->upperoverlay = R_LoadHiResTexture(va("%s_shirt", imagename), subpath, imageflags); + } + } + + if (!TEXVALID(tex->specular)) + { + extern cvar_t gl_specular; + if ((shader->flags & SHADER_HASGLOSS) && gl_specular.value && gl_load24bit.value) + { + if (!TEXVALID(tex->specular) && *mapname) + tex->specular = R_LoadHiResTexture(va("%s_gloss", mapname), NULL, imageflags); + if (!TEXVALID(tex->specular)) + tex->specular = R_LoadHiResTexture(va("%s_gloss", imagename), subpath, imageflags); + } + } + + if (!TEXVALID(tex->fullbright)) + { + extern cvar_t r_fb_bmodels; + if ((shader->flags & SHADER_HASFULLBRIGHT) && r_fb_bmodels.value && gl_load24bit.value) + { + if (!TEXVALID(tex->fullbright) && *mapname) + tex->fullbright = R_LoadHiResTexture(va("%s_luma", mapname), NULL, imageflags); + if (!TEXVALID(tex->fullbright)) + tex->fullbright = R_LoadHiResTexture(va("%s_luma", imagename), subpath, imageflags); + } } - TEXASSIGN(shader->defaulttextures.fullbright, tn->fullbright); } } @@ -4267,8 +4399,10 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons { char *h; char imagename[MAX_QPATH]; + char mapname[MAX_QPATH]; //as specified by the shader. //extern cvar_t gl_miptexLevel; - texnums_t *tex = &shader->defaulttextures; + texnums_t *tex = shader->defaulttextures; + int a, aframes; unsigned int imageflags; qbyte *dontcrashme[4] = {NULL}; if (!mipdata) @@ -4310,89 +4444,125 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons COM_StripExtension(imagename, imagename, sizeof(imagename)); - /*dlights/realtime lighting needs some stuff*/ - if (loadflags & SHADER_HASDIFFUSE) + aframes = max(1, shader->numdefaulttextures); + //if any were specified explicitly, replicate that into all. + //this means animmap can be used, with any explicit textures overriding all. + for (a = 1; a < aframes; a++) { - if (!TEXVALID(tex->base) && *shader->mapname) - tex->base = R_LoadHiResTexture(shader->mapname, NULL, imageflags); - if (!TEXVALID(tex->base) && fallbackname) + if (!TEXVALID(tex[a].base)) + tex[a].base = tex[0].base; + if (!TEXVALID(tex[a].bump)) + tex[a].bump = tex[0].bump; + if (!TEXVALID(tex[a].fullbright)) + tex[a].fullbright = tex[0].fullbright; + if (!TEXVALID(tex[a].specular)) + tex[a].specular = tex[0].specular; + if (!TEXVALID(tex[a].loweroverlay)) + tex[a].loweroverlay = tex[0].loweroverlay; + if (!TEXVALID(tex[a].upperoverlay)) + tex[a].upperoverlay = tex[0].upperoverlay; + if (!TEXVALID(tex[a].reflectmask)) + tex[a].reflectmask = tex[0].reflectmask; + if (!TEXVALID(tex[a].reflectcube)) + tex[a].reflectcube = tex[0].reflectcube; + } + for (a = 0; a < aframes; a++, tex++) + { + COM_StripExtension(tex->mapname, mapname, sizeof(mapname)); + + /*dlights/realtime lighting needs some stuff*/ + if (loadflags & SHADER_HASDIFFUSE) { - if (gl_load24bit.ival) + if (!TEXVALID(tex->base) && *mapname) + tex->base = R_LoadHiResTexture(mapname, NULL, imageflags); + if (!TEXVALID(tex->base) && fallbackname) { - tex->base = Image_GetTexture(imagename, subpath, imageflags|IF_NOWORKER, NULL, NULL, width, height, basefmt); - if (!TEXLOADED(tex->base)) + if (gl_load24bit.ival) { - tex->base = Image_GetTexture(fallbackname, subpath, imageflags|IF_NOWORKER, NULL, NULL, width, height, basefmt); - if (TEXLOADED(tex->base)) - Q_strncpyz(imagename, fallbackname, sizeof(imagename)); + tex->base = Image_GetTexture(imagename, subpath, imageflags|IF_NOWORKER, NULL, NULL, width, height, basefmt); + if (!TEXLOADED(tex->base)) + { + tex->base = Image_GetTexture(fallbackname, subpath, imageflags|IF_NOWORKER, NULL, NULL, width, height, basefmt); + if (TEXLOADED(tex->base)) + Q_strncpyz(imagename, fallbackname, sizeof(imagename)); + } } + if (!TEXLOADED(tex->base)) + tex->base = Image_GetTexture(imagename, subpath, imageflags, mipdata[0], palette, width, height, basefmt); } - if (!TEXLOADED(tex->base)) + else if (!TEXVALID(tex->base)) tex->base = Image_GetTexture(imagename, subpath, imageflags, mipdata[0], palette, width, height, basefmt); } - else if (!TEXVALID(tex->base)) - tex->base = Image_GetTexture(imagename, subpath, imageflags, mipdata[0], palette, width, height, basefmt); - } - if (loadflags & SHADER_HASPALETTED) - { - if (!TEXVALID(tex->paletted) && *shader->mapname) - tex->paletted = R_LoadHiResTexture(va("%s_pal", shader->mapname), NULL, imageflags|IF_NEAREST); - if (!TEXVALID(tex->paletted)) - tex->paletted = Image_GetTexture(va("%s_pal", imagename), subpath, imageflags|IF_NEAREST, mipdata[0], palette, width, height, (basefmt==TF_MIP4_SOLID8)?TF_MIP4_LUM8:TF_LUM8); - } - - imageflags |= IF_LOWPRIORITY; - //all the rest need/want an alpha channel in some form. - imageflags &= ~IF_NOALPHA; - imageflags |= IF_NOGAMMA; - - if (loadflags & SHADER_HASNORMALMAP) - { - extern cvar_t r_shadow_bumpscale_basetexture; - if (!TEXVALID(tex->bump) && *shader->mapname) - tex->bump = R_LoadHiResTexture(va("%s_norm", shader->mapname), NULL, imageflags|IF_TRYBUMP); - if (!TEXVALID(tex->bump) && (r_shadow_bumpscale_basetexture.ival||*imagename=='*'||gl_load24bit.ival)) - tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP, (r_shadow_bumpscale_basetexture.ival||*imagename=='*')?mipdata[0]:NULL, palette, width, height, TF_HEIGHT8PAL); - } - - if (loadflags & SHADER_HASTOPBOTTOM) - { - if (!TEXVALID(tex->loweroverlay) && *shader->mapname) - tex->loweroverlay = R_LoadHiResTexture(va("%s_pants", shader->mapname), NULL, imageflags); - if (!TEXVALID(tex->loweroverlay)) - tex->loweroverlay = Image_GetTexture(va("%s_pants", imagename), subpath, imageflags, NULL, palette, width, height, 0); - } - if (loadflags & SHADER_HASTOPBOTTOM) - { - if (!TEXVALID(tex->upperoverlay) && *shader->mapname) - tex->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->mapname), NULL, imageflags); - if (!TEXVALID(tex->upperoverlay)) - tex->upperoverlay = Image_GetTexture(va("%s_shirt", imagename), subpath, imageflags, NULL, palette, width, height, 0); - } - - if (loadflags & SHADER_HASGLOSS) - { - if (!TEXVALID(tex->specular) && *shader->mapname) - tex->specular = R_LoadHiResTexture(va("%s_gloss", shader->mapname), NULL, imageflags); - if (!TEXVALID(tex->specular)) - tex->specular = Image_GetTexture(va("%s_gloss", imagename), subpath, imageflags, NULL, palette, width, height, 0); - } - - if (loadflags & SHADER_HASFULLBRIGHT) - { - if (!TEXVALID(tex->fullbright) && *shader->mapname) - tex->fullbright = R_LoadHiResTexture(va("%s_luma", shader->mapname), NULL, imageflags); - if (!TEXVALID(tex->fullbright)) + if (loadflags & SHADER_HASPALETTED) { - int s=-1; - if (mipdata[0]) - for(s = width*height; s-->0; ) + if (!TEXVALID(tex->paletted) && *mapname) + tex->paletted = R_LoadHiResTexture(va("%s_pal", mapname), NULL, imageflags|IF_NEAREST); + if (!TEXVALID(tex->paletted)) + tex->paletted = Image_GetTexture(va("%s_pal", imagename), subpath, imageflags|IF_NEAREST, mipdata[0], palette, width, height, (basefmt==TF_MIP4_SOLID8)?TF_MIP4_LUM8:TF_LUM8); + } + + imageflags |= IF_LOWPRIORITY; + //all the rest need/want an alpha channel in some form. + imageflags &= ~IF_NOALPHA; + imageflags |= IF_NOGAMMA; + + if (loadflags & SHADER_HASNORMALMAP) + { + extern cvar_t r_shadow_bumpscale_basetexture; + if (!TEXVALID(tex->bump) && *mapname) + tex->bump = R_LoadHiResTexture(va("%s_norm", mapname), NULL, imageflags|IF_TRYBUMP); + if (!TEXVALID(tex->bump) && (r_shadow_bumpscale_basetexture.ival||*imagename=='*'||gl_load24bit.ival)) + tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP, (r_shadow_bumpscale_basetexture.ival||*imagename=='*')?mipdata[0]:NULL, palette, width, height, TF_HEIGHT8PAL); + } + + if (loadflags & SHADER_HASTOPBOTTOM) + { + if (!TEXVALID(tex->loweroverlay) && *mapname) + tex->loweroverlay = R_LoadHiResTexture(va("%s_pants", mapname), NULL, imageflags); + if (!TEXVALID(tex->loweroverlay)) + tex->loweroverlay = Image_GetTexture(va("%s_pants", imagename), subpath, imageflags, NULL, palette, width, height, 0); + } + if (loadflags & SHADER_HASTOPBOTTOM) + { + if (!TEXVALID(tex->upperoverlay) && *mapname) + tex->upperoverlay = R_LoadHiResTexture(va("%s_shirt", mapname), NULL, imageflags); + if (!TEXVALID(tex->upperoverlay)) + tex->upperoverlay = Image_GetTexture(va("%s_shirt", imagename), subpath, imageflags, NULL, palette, width, height, 0); + } + + if (loadflags & SHADER_HASGLOSS) + { + if (!TEXVALID(tex->specular) && *mapname) + tex->specular = R_LoadHiResTexture(va("%s_gloss", mapname), NULL, imageflags); + if (!TEXVALID(tex->specular)) + tex->specular = Image_GetTexture(va("%s_gloss", imagename), subpath, imageflags, NULL, palette, width, height, 0); + } + + if (tex->reflectcube) + { + extern cvar_t r_shadow_bumpscale_basetexture; + if (!TEXVALID(tex->reflectmask) && *mapname) + tex->reflectmask = R_LoadHiResTexture(va("%s_reflect", mapname), NULL, imageflags); + if (!TEXVALID(tex->reflectmask)) + tex->reflectmask = Image_GetTexture(va("%s_reflect", imagename), subpath, imageflags, NULL, NULL, width, height, TF_INVALID); + } + + if (loadflags & SHADER_HASFULLBRIGHT) + { + if (!TEXVALID(tex->fullbright) && *mapname) + tex->fullbright = R_LoadHiResTexture(va("%s_luma", mapname), NULL, imageflags); + if (!TEXVALID(tex->fullbright)) { - if (mipdata[0][s] >= 256-vid.fullbright) - break; + int s=-1; + if (mipdata[0]) + for(s = width*height; s-->0; ) + { + if (mipdata[0][s] >= 256-vid.fullbright) + break; + } + tex->fullbright = Image_GetTexture(va("%s_luma", imagename), subpath, imageflags, (s>=0)?mipdata[0]:NULL, palette, width, height, TF_TRANS8_FULLBRIGHT); } - tex->fullbright = Image_GetTexture(va("%s_luma", imagename), subpath, imageflags, (s>=0)?mipdata[0]:NULL, palette, width, height, TF_TRANS8_FULLBRIGHT); } } } @@ -4935,9 +5105,9 @@ void Shader_DefaultBSPVertex(const char *shortname, shader_t *s, const void *arg } else*/ { - s->defaulttextures.base = R_LoadHiResTexture(shortname, NULL, 0); + s->defaulttextures->base = R_LoadHiResTexture(shortname, NULL, 0); pass->texgen = T_GEN_DIFFUSE; - if (!TEXVALID(s->defaulttextures.base)) + if (!TEXVALID(s->defaulttextures->base)) Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", s->name, shortname ); } @@ -5059,7 +5229,7 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs) "sort additive\n" "}\n" ); - TEXASSIGN(s->defaulttextures.base, R_LoadHiResTexture(s->name, NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); + TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); } else { @@ -5076,7 +5246,7 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs) "sort additive\n" "}\n" ); - TEXASSIGN(s->defaulttextures.base, R_LoadHiResTexture(s->name, NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); + TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); } } @@ -5327,11 +5497,18 @@ static shader_t *R_LoadShader (const char *name, unsigned int usageflags, shader s = r_shaders[f]; if (!s) + { s = r_shaders[f] = Z_Malloc(sizeof(*s)); + } s->id = f; if (r_numshaders < f+1) r_numshaders = f+1; + if (!s->defaulttextures) + { + s->defaulttextures = Z_Malloc(sizeof(*s->defaulttextures)); + s->numdefaulttextures = 0; + } Q_strncpyz(s->name, cleanname, sizeof(s->name)); s->usageflags = usageflags; s->generator = defaultgen; @@ -5673,11 +5850,11 @@ int R_GetShaderSizes(shader_t *shader, int *width, int *height, qboolean blockti return -1; COM_WorkerPartialSync(shader->passes[i].anim_frames[0], &shader->passes[i].anim_frames[0]->status, TEX_LOADING); } - if (shader->passes[i].texgen == T_GEN_DIFFUSE && (shader->defaulttextures.base && shader->defaulttextures.base->status == TEX_LOADING)) + if (shader->passes[i].texgen == T_GEN_DIFFUSE && (shader->defaulttextures->base && shader->defaulttextures->base->status == TEX_LOADING)) { if (!blocktillloaded) return -1; - COM_WorkerPartialSync(shader->defaulttextures.base, &shader->defaulttextures.base->status, TEX_LOADING); + COM_WorkerPartialSync(shader->defaulttextures->base, &shader->defaulttextures->base->status, TEX_LOADING); } } @@ -5693,12 +5870,12 @@ int R_GetShaderSizes(shader_t *shader, int *width, int *height, qboolean blockti } break; } - if (shader->passes[i].texgen == T_GEN_DIFFUSE && shader->defaulttextures.base) + if (shader->passes[i].texgen == T_GEN_DIFFUSE && shader->defaulttextures->base) { - if (shader->defaulttextures.base->status == TEX_LOADED) + if (shader->defaulttextures->base->status == TEX_LOADED) { - shader->width = shader->defaulttextures.base->width; - shader->height = shader->defaulttextures.base->height; + shader->width = shader->defaulttextures->base->width; + shader->height = shader->defaulttextures->base->height; } break; } diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 7e6401c33..ea5796fa2 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -2230,7 +2230,7 @@ static void Sh_GenShadowFace(dlight_t *l, vec3_t axis[3], shadowmesh_t *smesh, i tex = cl.worldmodel->shadowbatches[tno].tex; if (tex->shader->flags & SHADER_NODLIGHT) //FIXME: shadows not lights continue; - BE_DrawMesh_List(tex->shader, smesh->batches[tno].count, smesh->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0); + BE_DrawMesh_List(tex->shader, smesh->batches[tno].count, smesh->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, NULL, 0); } break; } @@ -2606,7 +2606,7 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) if (shader->flags & SHADER_NODLIGHT) continue; //FIXME: it may be worth building a dedicated ebo - BE_DrawMesh_List(shader, sm->batches[tno].count, sm->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &shader->defaulttextures, 0); + BE_DrawMesh_List(shader, sm->batches[tno].count, sm->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, NULL, 0); RQuantAdd(RQUANT_LITFACES, sm->batches[tno].count); } @@ -3226,7 +3226,7 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours) BE_SelectMode(BEM_STANDARD); - GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0); + BE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, 0); GLBE_FBO_Sources(oldsrccol, NULL); #endif diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index c417dc978..20c8ab8a4 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -1002,6 +1002,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow"); //gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2. nvidia fucks up. depend on brute-force. :s + if (GL_CheckExtension("GL_ARB_seamless_cube_map")) + qglEnable(0x884F); //TEXTURE_CUBE_MAP_SEAMLESS 0x884F + #ifdef GL_STATIC gl_config.ext_framebuffer_objects = true; //exists as core in gles2 #else @@ -1124,6 +1127,8 @@ static const char *glsl_hdrs[] = "uniform sampler2D s_paletted;\n" "uniform sampler2D s_shadowmap;\n" "uniform samplerCube s_projectionmap;\n" + "uniform samplerCube s_reflectcube;\n" + "uniform sampler2D s_reflectmask;\n" "uniform sampler2D s_lightmap;\n" "uniform sampler2D s_deluxmap;\n" #if MAXRLIGHTMAPS > 1 @@ -2206,6 +2211,8 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart "s_paletted", "s_shadowmap", "s_projectionmap", + "s_reflectcube", + "s_reflectmask", "s_lightmap", "s_deluxmap" #if MAXRLIGHTMAPS > 1 @@ -2217,6 +2224,8 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart ,"s_deluxmap3" #endif }; +#define ALTLIGHTMAPSAMP 13 +#define ALTDELUXMAPSAMP 16 unsigned int i, p; qboolean found; @@ -2348,10 +2357,10 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart } //multiple lightmaps is kinda hacky. if any are set, all must be. - if (prog->defaulttextures & ((1u<<11) | (1u<<12) | (1u<<13))) - prog->defaulttextures |=((1u<<11) | (1u<<12) | (1u<<13)); - if (prog->defaulttextures & ((1u<<14) | (1u<<15) | (1u<<16))) - prog->defaulttextures |=((1u<<14) | (1u<<15) | (1u<<16)); + if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)))) + prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))); + if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)))) + prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))); if (prog->defaulttextures) { diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index baf3d0dcb..6363c77d5 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -107,6 +107,12 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info); //-1 on bpp or hz for defau qboolean scr_skipupdate; +//#define WTHREAD +#ifdef WTHREAD +static HANDLE windowthread; +static void *windowmutex; +#endif + static DEVMODE gdevmode; static qboolean vid_initialized = false; static qboolean vid_canalttab = false; @@ -1013,12 +1019,43 @@ static qboolean CreateMainWindow(rendererstate_t *info) return stat; } + +#ifdef WTHREAD +rendererstate_t *rs; +int GLVID_WindowThread(void *cond) +{ + extern qboolean mouseshowtoggle; + int cursor = 1; + MSG msg; + HWND wnd; + CreateMainWindow(rs); + wnd = mainwindow; + Sys_ConditionSignal(cond); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + + //ShowCursor is thread-local. + if (cursor != mouseshowtoggle) + { + cursor = mouseshowtoggle; + ShowCursor(cursor); + } + } + DestroyWindow(wnd); + return 0; +} +#endif + BOOL CheckForcePixelFormat(rendererstate_t *info); void VID_UnSetMode (void); int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) { int temp; qboolean stat; + void *cond; #ifndef NPFTE MSG msg; #endif @@ -1035,7 +1072,22 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) // Set either the fullscreen or windowed mode qwglChoosePixelFormatARB = NULL; qwglCreateContextAttribsARB = NULL; + +#ifdef WTHREAD + cond = Sys_CreateConditional(); + Sys_LockConditional(cond); + rs = info; + windowthread = Sys_CreateThread("windowthread", GLVID_WindowThread, cond, 0, 0); + if (!Sys_ConditionWait(cond)) + Con_SafePrintf ("Looks like the window thread isn't starting up\n"); + Sys_UnlockConditional(cond); + Sys_DestroyConditional(cond); + + stat = !!mainwindow; +#else stat = CreateMainWindow(info); +#endif + if (stat) { stat = VID_AttachGL(info); @@ -1168,7 +1220,16 @@ void VID_UnSetMode (void) // ShowWindow(mainwindow, SW_HIDE); // SetWindowLongPtr(mainwindow, GWL_WNDPROC, DefWindowProc); // PostMessage(mainwindow, WM_CLOSE, 0, 0); - DestroyWindow(mainwindow); +#ifdef WTHREAD + if (windowthread) + { + SendMessage(mainwindow, WM_USER+4, 0, 0); + CloseHandle((HANDLE)windowthread); + windowthread = NULL; + } + else +#endif + DestroyWindow(mainwindow); mainwindow = NULL; } @@ -2087,8 +2148,40 @@ static void Win_Touch_Event(int points, HTOUCHINPUT ti) pCloseTouchInputHandle(ti); } +#ifdef WTHREAD +void MainThreadWndProc(void *ctx, void *data, size_t msg, size_t ex) +{ + switch(msg) + { + case WM_COPYDATA: + Host_RunFile(data, ex, NULL); + Z_Free(data); + break; + case WM_SIZE: + case WM_MOVE: + Cvar_ForceCallback(&vid_conautoscale); //FIXME: thread + break; + case WM_KILLFOCUS: + GLAppActivate(FALSE, Minimized);//FIXME: thread + if (modestate == MS_FULLDIB) + ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); + ClearAllStates (); //FIXME: thread + break; + case WM_SETFOCUS: + if (!GLAppActivate(TRUE, Minimized))//FIXME: thread + break; + ClearAllStates (); //FIXME: thread + break; + } +} +#endif -/* main window procedure */ +/* main window procedure +due to moving the main window over to a different thread, we gain access to input timestamps (as well as video refreshes when dragging etc) +however, we have to tread carefully. the main/render thread will be running the whole time, and may trigger messages that we need to respond to _now_. +this means that the main and window thread cannot be allowed to contest any mutexes where anything but memory is touched before its unlocked. +(or in other words, we can't have the main thread near-perma-lock any mutexes that can be locked-to-sync here) +*/ LONG WINAPI GLMainWndProc ( HWND hWnd, UINT uMsg, @@ -2108,20 +2201,32 @@ LONG WINAPI GLMainWndProc ( case WM_COPYDATA: { COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam; +#ifdef WTHREAD + COM_AddWork(0, MainThreadWndProc, NULL, memcpy(Z_Malloc(cds->cbData), cds->lpData, cds->cbData), uMsg, cds->cbData); +#else Host_RunFile(cds->lpData, cds->cbData, NULL); +#endif lRet = 1; } break; case WM_KILLFOCUS: - GLAppActivate(FALSE, Minimized); +#ifdef WTHREAD + COM_AddWork(0, MainThreadWndProc, NULL, NULL, uMsg, 0); +#else + GLAppActivate(FALSE, Minimized);//FIXME: thread if (modestate == MS_FULLDIB) ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); - ClearAllStates (); + ClearAllStates (); //FIXME: thread +#endif break; case WM_SETFOCUS: - if (!GLAppActivate(TRUE, Minimized)) +#ifdef WTHREAD + COM_AddWork(0, MainThreadWndProc, NULL, NULL, uMsg, 0); +#else + if (!GLAppActivate(TRUE, Minimized))//FIXME: thread break; - ClearAllStates (); + ClearAllStates (); //FIXME: thread +#endif break; case WM_TOUCH: @@ -2133,7 +2238,11 @@ LONG WINAPI GLMainWndProc ( case WM_MOVE: VID_UpdateWindowStatus (hWnd); +#ifdef WTHREAD + COM_AddWork(0, MainThreadWndProc, NULL, NULL, uMsg, 0); +#else Cvar_ForceCallback(&vid_conautoscale); +#endif break; case WM_KEYDOWN: @@ -2209,7 +2318,7 @@ LONG WINAPI GLMainWndProc ( temp |= 512; if (!vid_initializing) - INS_MouseEvent (temp); + INS_MouseEvent (temp); //FIXME: thread (halflife) break; @@ -2221,13 +2330,13 @@ LONG WINAPI GLMainWndProc ( { if ((short) HIWORD(wParam&0xffffffff) > 0) { - Key_Event(0, K_MWHEELUP, 0, true); - Key_Event(0, K_MWHEELUP, 0, false); + IN_KeyEvent(0, true, K_MWHEELUP, 0); + IN_KeyEvent(0, false, K_MWHEELUP, 0); } else { - Key_Event(0, K_MWHEELDOWN, 0, true); - Key_Event(0, K_MWHEELDOWN, 0, false); + IN_KeyEvent(0, true, K_MWHEELDOWN, 0); + IN_KeyEvent(0, false, K_MWHEELDOWN, 0); } } break; @@ -2241,6 +2350,9 @@ LONG WINAPI GLMainWndProc ( } break; + case WM_USER+4: + PostQuitMessage(0); + break; case WM_USER: #ifndef NOMEDIA STT_Event(); @@ -2265,13 +2377,17 @@ LONG WINAPI GLMainWndProc ( if (!vid_initializing) { VID_UpdateWindowStatus (hWnd); +#ifdef WTHREAD + COM_AddWork(0, MainThreadWndProc, NULL, NULL, uMsg, 0); +#else Cvar_ForceCallback(&vid_conautoscale); +#endif } break; case WM_CLOSE: if (!vid_initializing) - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + if (MessageBox (hWnd, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); @@ -2280,24 +2396,28 @@ LONG WINAPI GLMainWndProc ( break; + case WM_ERASEBKGND: + lRet = TRUE; + break; +/* case WM_ACTIVATE: // fActive = LOWORD(wParam); // fMinimized = (BOOL) HIWORD(wParam); // if (!GLAppActivate(!(fActive == WA_INACTIVE), fMinimized)) break;//so, urm, tell me microsoft, what changed? if (modestate == MS_FULLDIB) - ShowWindow(mainwindow, SW_SHOWNORMAL); + ShowWindow(hWnd, SW_SHOWNORMAL); +#ifdef WTHREAD +#else // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - Cvar_ForceCallback(&vid_conautoscale); + ClearAllStates (); //FIXME: thread + Cvar_ForceCallback(&vid_conautoscale); //FIXME: thread +#endif break; - +*/ case WM_DESTROY: - if (dibwindow) - DestroyWindow (dibwindow); break; case WM_SETCURSOR: //only use a custom cursor if the cursor is inside the client area @@ -2318,9 +2438,11 @@ LONG WINAPI GLMainWndProc ( } break; +#ifndef WTHREAD case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); //FIXME: thread break; +#endif default: /* pass all unhandled messages to DefWindowProc */ diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index e3b597d1e..4d9f230d2 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -90,7 +90,7 @@ void R_DrawSkyChain (batch_t *batch) if (skyshader->numpasses) { #if defined(GLQUAKE) && !defined(ANDROID) - if (*r_fastsky.string && qrenderer == QR_OPENGL && TEXVALID(batch->shader->defaulttextures.base) && TEXVALID(batch->shader->defaulttextures.fullbright)) + if (*r_fastsky.string && qrenderer == QR_OPENGL && TEXVALID(batch->shader->defaulttextures->base) && TEXVALID(batch->shader->defaulttextures->fullbright)) { R_CalcSkyChainBounds(batch); @@ -459,7 +459,7 @@ static void GL_SkyForceDepth(batch_t *batch) if (!cls.allow_skyboxes && batch->texture) //allow a little extra fps. { BE_SelectMode(BEM_DEPTHONLY); - BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, batch->vbo, &batch->shader->defaulttextures, batch->flags); + BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, batch->vbo, NULL, batch->flags); BE_SelectMode(BEM_STANDARD); /*skys only render in standard mode anyway, so this is safe*/ } } @@ -494,7 +494,7 @@ static void R_DrawSkyMesh(batch_t *batch, mesh_t *m, shader_t *shader) b.mesh = &m; b.ent = &skyent; b.shader = shader; - b.skin = &shader->defaulttextures; + b.skin = NULL; b.texture = NULL; b.vbo = NULL; BE_SubmitBatch(&b); @@ -643,7 +643,7 @@ static void GL_DrawSkyGrid (texture_t *tex) int i; float time = cl.gametime+realtime-cl.gametimemark; - GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.base); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures->base); speedscale = time*8; speedscale -= (int)speedscale & ~127; @@ -656,7 +656,7 @@ static void GL_DrawSkyGrid (texture_t *tex) } qglEnable (GL_BLEND); - GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.fullbright); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures->fullbright); speedscale = time*16; speedscale -= (int)speedscale & ~127; @@ -730,7 +730,7 @@ static void GL_DrawSkyBox (texid_t *texnums, batch_t *s) GL_MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, skyface_vertex[2], skyface_texcoord[2]); GL_MakeSkyVec (skymaxs[0][i], skymins[1][i], i, skyface_vertex[3], skyface_texcoord[3]); - skyboxface->defaulttextures.base = texnums[skytexorder[i]]; + skyboxface->defaulttextures->base = texnums[skytexorder[i]]; R_DrawSkyMesh(s, &skyfacemesh, skyboxface); } } @@ -744,7 +744,7 @@ R_InitSky A sky texture is 256*128, with the right side being a masked overlay ============== */ -void R_InitSky (struct texnums_s *tn, const char *skyname, qbyte *src, unsigned int width, unsigned int height) +void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int width, unsigned int height) { int i, j, p; unsigned trans[128*128]; @@ -756,8 +756,6 @@ void R_InitSky (struct texnums_s *tn, const char *skyname, qbyte *src, unsigned unsigned int stride = width; width /= 2; - memset(tn, 0, sizeof(*tn)); - if (width < 1 || height < 1 || stride != width*2) return; @@ -776,28 +774,34 @@ void R_InitSky (struct texnums_s *tn, const char *skyname, qbyte *src, unsigned b += ((qbyte *)rgba)[2]; } - Q_snprintfz(name, sizeof(name), "%s_solid", skyname); - Q_strlwr(name); - tn->base = R_LoadReplacementTexture(name, NULL, IF_NOALPHA, trans, width, height, TF_RGBX32); + if (!shader->defaulttextures->base) + { + Q_snprintfz(name, sizeof(name), "%s_solid", skyname); + Q_strlwr(name); + shader->defaulttextures->base = R_LoadReplacementTexture(name, NULL, IF_NOALPHA, trans, width, height, TF_RGBX32); + } - ((qbyte *)&transpix)[0] = r/(width*height); - ((qbyte *)&transpix)[1] = g/(width*height); - ((qbyte *)&transpix)[2] = b/(width*height); - ((qbyte *)&transpix)[3] = 0; - alphamask = LittleLong(0x7fffffff); - for (i=0 ; idefaulttextures->fullbright) + { + ((qbyte *)&transpix)[0] = r/(width*height); + ((qbyte *)&transpix)[1] = g/(width*height); + ((qbyte *)&transpix)[2] = b/(width*height); + ((qbyte *)&transpix)[3] = 0; + alphamask = LittleLong(0x7fffffff); + for (i=0 ; ifullbright = R_LoadReplacementTexture(name, NULL, 0, trans, width, height, TF_RGBA32); + //FIXME: support _trans + Q_snprintfz(name, sizeof(name), "%s_alpha", skyname); + Q_strlwr(name); + shader->defaulttextures->fullbright = R_LoadReplacementTexture(name, NULL, 0, trans, width, height, TF_RGBA32); + } } #endif diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index e728cdf0e..d9a55a7a0 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -390,17 +390,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "struct a2v\n" "{\n" "float4 pos: POSITION;\n" -"float3 normal: NORMAL;\n" -"#ifdef MASK\n" -"float4 tc: TEXCOORD0;\n" -"#endif\n" "};\n" "struct v2f\n" "{\n" +"float3 col: TEXCOORD;\n" "float4 pos: SV_POSITION;\n" -"#ifdef MASK\n" -"float2 tc: TEXCOORD0;\n" -"#endif\n" "};\n" "#include \n" @@ -412,44 +406,25 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "outp.pos = mul(m_model, inp.pos);\n" "outp.pos = mul(m_view, outp.pos);\n" "outp.pos = mul(m_projection, outp.pos);\n" - -"#ifdef MASK\n" -"outp.tc = inp.tc.xy;\n" -"#endif\n" - +"outp.col = inp.pos.xyz - l_lightposition;\n" "return outp;\n" "}\n" "#endif\n" -"#ifdef FRAGMENT_SHADER\n" -"#ifdef MASK\n" -"Texture2D shaderTexture[1];\n" -"SamplerState SampleType[1];\n" -"#endif\n" -"#if LEVEL < 1000\n" +"#ifdef FRAGMENT_SHADER\n" +"#if LEVEL < 0x10000\n" //pre dx10 requires that we ALWAYS write to a target. "float4 main (v2f inp) : SV_TARGET\n" +"{\n" +"return float4(0, 0, 0, 1);\n" +"}\n" "#else\n" //but on 10, it'll write depth automatically and we don't care about colour. -"void main (v2f inp) //dx10-level\n" -"#endif\n" +"void main (v2f inp)\n" "{\n" - -"#ifdef MASK\n" -"float alpha = shaderTexture[0].Sample(SampleType[0], inp.tc).a;\n" -"#ifndef MASKOP\n" -"#define MASKOP >= //drawn if (alpha OP ref) is true.\n" -"#endif\n" -//support for alpha masking -"if (!(alpha MASKOP MASK))\n" -"discard;\n" -"#endif\n" - -"#if LEVEL < 1000\n" -"return float4(0, 0, 0, 1);\n" -"#endif\n" "}\n" "#endif\n" +"#endif\n" }, #endif #ifdef GLQUAKE @@ -507,9 +482,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "v2f main (a2v inp)\n" "{\n" "v2f outp;\n" -"outp.pos = mul(m_model, inp.pos);\n" -"outp.pos = mul(m_view, outp.pos);\n" -"outp.pos = mul(m_projection, outp.pos);\n" +"outp.pos = mul(m_projection, inp.pos);\n" "outp.tc = inp.tc;\n" "outp.vcol = inp.vcol;\n" "return outp;\n" @@ -517,11 +490,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture;\n" -"SamplerState SampleType;\n" +"Texture2D t_t0;\n" +"SamplerState s_t0;\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" -"return shaderTexture.Sample(SampleType, inp.tc) * inp.vcol;\n" +"return t_t0.Sample(s_t0, inp.tc) * inp.vcol;\n" "}\n" "#endif\n" }, @@ -693,14 +666,22 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "}\n" "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture[4]; //diffuse, lower, upper, fullbright\n" +"Texture2D t_diffuse : register(t0);\n" +"#ifdef UPPER\n" +"Texture2D t_upper : register(t1);\n" +"Texture2D t_lower : register(t2);\n" +"Texture2D t_fullbright : register(t3);\n" +"#else\n" +"Texture2D t_fullbright : register(t1);\n" +"#endif\n" + "SamplerState SampleType;\n" //uniform vec4 e_colourident; "float4 main (v2f inp) : SV_TARGET\n" "{\n" "float4 col;\n" -"col = shaderTexture[0].Sample(SampleType, inp.tc);\n" +"col = t_diffuse.Sample(SampleType, inp.tc);\n" "#ifdef MASK\n" "#ifndef MASKOP\n" @@ -712,18 +693,18 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef UPPER\n" -"float4 uc = shaderTexture[2].Sample(SampleType, inp.tc);\n" -"col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n" +"float4 uc = t_upper.Sample(SampleType, inp.tc);\n" +"col.rgb = lerp(col.rgb, uc.rgb*e_uppercolour, uc.a);\n" "#endif\n" "#ifdef LOWER\n" -"float4 lc = shaderTexture[1].Sample(SampleType, inp.tc);\n" -"col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n" +"float4 lc = t_lower.Sample(SampleType, inp.tc);\n" +"col.rgb = lerp(col.rgb, lc.rgb*e_lowercolour, lc.a);\n" "#endif\n" "col.rgb *= inp.light;\n" -"#ifdef FULLBRIGHT\n" -"float4 fb = shaderTexture[3].Sample(SampleType, inp.tc);\n" -"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" -"#endif\n" +//#ifdef FULLBRIGHT +"float4 fb = t_fullbright.Sample(SampleType, inp.tc);\n" +"col.rgb = lerp(col.rgb, fb.rgb, fb.a);\n" +//#endif "return col;\n" // return fog4(col * e_colourident); "}\n" @@ -852,8 +833,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture[2];\n" -"SamplerState SampleType;\n" +"Texture2D t_diffuse : register(t0);\n" +"Texture2D t_fullbright : register(t1);\n" +"SamplerState s_diffuse : register(s0);\n" +"SamplerState s_fullbright : register(s1);\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" @@ -862,10 +845,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "dir.z *= 3.0;\n" "dir.xy /= 0.5*length(dir);\n" "tccoord = (dir.xy + e_time*0.03125);\n" -"float4 solid = shaderTexture[0].Sample(SampleType, tccoord);\n" +"float4 solid = t_diffuse.Sample(s_diffuse, tccoord);\n" "tccoord = (dir.xy + e_time*0.0625);\n" -"float4 clouds = shaderTexture[1].Sample(SampleType, tccoord);\n" -"return (solid*(1.0-clouds.a)) + (clouds.a*clouds);\n" +"float4 clouds = t_fullbright.Sample(s_fullbright, tccoord);\n" +"return lerp(solid, clouds, clouds.a);\n" "}\n" "#endif\n" }, @@ -992,11 +975,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture;\n" -"SamplerState SampleType;\n" +"Texture2D t_diffuse : register(t0);\n" +"SamplerState s_diffuse : register(s0);\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" -"float4 tex = shaderTexture.Sample(SampleType, inp.tc);\n" +"float4 tex = t_diffuse.Sample(s_diffuse, inp.tc);\n" "#ifdef MASK\n" "if (tex.a < float(MASK))\n" "discard;\n" @@ -1015,6 +998,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "!!permu LIGHTSTYLED\n" "!!permu BUMP\n" "!!permu SPECULAR\n" +"!!permu REFLECTCUBEMASK\n" "!!cvarf r_glsl_offsetmapping_scale\n" "!!cvarf gl_specular\n" @@ -1024,10 +1008,14 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //note that the '286' preset uses drawflat_walls instead. "#include \"sys/fog.h\"\n" -"#if defined(OFFSETMAPPING) || defined(SPECULAR)\n" +"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n" "varying vec3 eyevector;\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"varying mat3 invsurface;\n" +"#endif\n" + "varying vec2 tc;\n" "#ifdef LIGHTSTYLED\n" //we could use an offset, but that would still need to be per-surface which would break batches @@ -1040,12 +1028,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef VERTEX_SHADER\n" "void main ()\n" "{\n" -"#if defined(OFFSETMAPPING) || defined(SPECULAR)\n" +"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n" "vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n" "eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n" "eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n" "eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"invsurface[0] = v_svector;\n" +"invsurface[1] = v_tvector;\n" +"invsurface[2] = v_normal;\n" +"#endif\n" "tc = v_texcoord;\n" "lm0 = v_lmcoord;\n" "#ifdef LIGHTSTYLED\n" @@ -1090,9 +1083,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //yay, regular texture! "gl_FragColor = texture2D(s_diffuse, tc);\n" -"#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR))\n" +"#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))\n" "vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);\n" -"#elif defined(SPECULAR) || defined(DELUXE)\n" +"#elif defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)\n" "vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.\n" "#endif\n" @@ -1138,6 +1131,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "gl_FragColor.rgb += spec * specs.rgb;\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"vec3 rtc = reflect(-eyevector, norm);\n" +"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n" +"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n" +"gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;\n" +"#endif\n" + "#ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant.\n" "lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.\n" "float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated.\n" @@ -1155,7 +1155,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#endif\n" - //entity modifiers "gl_FragColor = gl_FragColor * e_colourident;\n" @@ -1197,24 +1196,23 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture[2];\n" -"SamplerState SampleType[2];\n" +"Texture2D t_lightmap : register(t2);\n" +"SamplerState s_lightmap : register(s2);\n" + +"Texture2D t_diffuse : register(s0);\n" +"SamplerState s_diffuse : register(s0);\n" + +"Texture2D t_fullbright : register(s1);\n" +"SamplerState s_fullbright : register(s1);\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" -"float4 tex = shaderTexture[0].Sample(SampleType[0], inp.tc);\n" -"float4 lm = shaderTexture[1].Sample(SampleType[1], inp.lmtc);\n" - -"#ifdef MASK\n" -"#ifndef MASKOP\n" -"#define MASKOP >= //drawn if (alpha OP ref) is true.\n" -"#endif\n" -//support for alpha masking -"if (!(tex.a MASKOP MASK))\n" -"discard;\n" -"#endif\n" - -"return tex * lm.bgra;\n" +"float4 result;\n" +"result = t_diffuse.Sample(s_diffuse, inp.tc);\n" +"result.rgb *= t_lightmap.Sample(s_lightmap, inp.lmtc).bgr * e_lmscale[0].rgb;\n" +"float4 fb = t_fullbright.Sample(s_fullbright, inp.tc);\n" +"result.rgb += fb.rgb * fb.a;//lerp(result.rgb, fb.rgb, fb.a);\n" +"return result;\n" "}\n" "#endif\n" }, @@ -1331,15 +1329,14 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" // float cvar_r_wateralpha; // float e_time; -// sampler s_t0; -"Texture2D shaderTexture;\n" -"SamplerState SampleType;\n" +"SamplerState s_diffuse;\n" +"Texture2D t_diffuse;\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" "float2 ntc;\n" "ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n" "ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n" -"return shaderTexture.Sample(SampleType, ntc);\n" +"return t_diffuse.Sample(s_diffuse, ntc);\n" "}\n" "#endif\n" }, @@ -1437,12 +1434,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#ifdef FRAGMENT_SHADER\n" -"Texture2D shaderTexture;\n" -"SamplerState SampleType;\n" +"Texture2D t_lightmap : register(t0);\n" +"SamplerState s_lightmap : register(s0);\n" "float4 main (v2f inp) : SV_TARGET\n" "{\n" -"return inp.col * shaderTexture.Sample(SampleType, inp.lmtc);\n" +"return inp.col * t_lightmap.Sample(s_lightmap, inp.lmtc);\n" "}\n" "#endif\n" }, @@ -1664,6 +1661,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "!!permu SKELETAL\n" "!!permu UPPERLOWER\n" "!!permu FOG\n" +"!!permu REFLECTCUBEMASK\n" "!!cvarf r_glsl_offsetmapping_scale\n" "!!cvardf r_glsl_pcf\n" @@ -1691,11 +1689,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#define r_glsl_pcf 9\n" "#endif\n" - -//texturegather is a gl4 feature, but these shaders are gl2.0 or something -"#if #include \"cvar/texgather\" && defined(GL_ARB_texture_gather) && defined(PCF) \n" +"#if 0 && defined(GL_ARB_texture_gather) && defined(PCF) \n" "#extension GL_ARB_texture_gather : enable\n" -"#define DOTEXTUREGATHER\n" "#endif\n" "#ifdef UPPERLOWER\n" @@ -1714,9 +1709,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "varying vec2 tcbase;\n" "varying vec3 lightvector;\n" -"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" "varying vec3 eyevector;\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"varying mat3 invsurface;\n" +"uniform mat4 m_model;\n" +"#endif\n" "#if defined(PCF) || defined(CUBE) || defined(SPOT)\n" "varying vec4 vtexprojcoord;\n" "#endif\n" @@ -1729,7 +1728,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#include \"sys/skeletal.h\"\n" "uniform vec3 l_lightposition;\n" "attribute vec2 v_texcoord;\n" -"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" "uniform vec3 e_eyepos;\n" "#endif\n" "void main ()\n" @@ -1747,12 +1746,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "lightvector.y = dot(lightminusvertex, t.xyz);\n" "lightvector.z = dot(lightminusvertex, n.xyz);\n" "#endif\n" -"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n" +"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" "vec3 eyeminusvertex = e_eyepos - w.xyz;\n" "eyevector.x = dot(eyeminusvertex, s.xyz);\n" "eyevector.y = dot(eyeminusvertex, t.xyz);\n" "eyevector.z = dot(eyeminusvertex, n.xyz);\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"invsurface[0] = v_svector;\n" +"invsurface[1] = v_tvector;\n" +"invsurface[2] = v_normal;\n" +"#endif\n" "#if defined(PCF) || defined(SPOT) || defined(CUBE)\n" //for texture projections/shadowmapping on dlights "vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n" @@ -1767,7 +1771,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#include \"sys/fog.h\"\n" "uniform sampler2D s_t0; //diffuse\n" -"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" "uniform sampler2D s_t1; //normalmap\n" "#endif\n" "#ifdef SPECULAR\n" @@ -1796,6 +1800,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform vec3 e_uppercolour;\n" "#endif\n" +"#ifdef REFLECTCUBEMASK\n" +"uniform sampler2D s_reflectmask;\n" +"uniform samplerCube s_reflectcube;\n" +"#endif\n" + "uniform float l_lightradius;\n" "uniform vec3 l_lightcolour;\n" @@ -1854,7 +1863,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "{\n" "vec3 shadowcoord = ShadowmapCoord();\n" -"#ifdef DOTEXTUREGATHER\n" +"#if 0//def GL_ARB_texture_gather\n" "vec2 ipart, fpart;\n" "#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n" "vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n" @@ -1924,8 +1933,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "vec4 lc = texture2D(s_t5, tcbase);\n" "bases.rgb += lc.rgb*e_lowercolour*lc.a;\n" "#endif\n" -"#if defined(BUMP) || defined(SPECULAR)\n" +"#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n" "vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n" +"#elif defined(REFLECTCUBEMASK)\n" +"vec3 bumps = vec3(0.0,0.0,1.0);\n" "#endif\n" "#ifdef SPECULAR\n" "vec4 specs = texture2D(s_t2, tcbase);\n" @@ -1953,7 +1964,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "diff += l_lightcolourscale.z * spec * specs.rgb;\n" "#endif\n" - +"#ifdef REFLECTCUBEMASK\n" +"vec3 rtc = reflect(-eyevector, bumps);\n" +"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n" +"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n" +"diff += texture2D(s_reflectmask, tcbase).rgb * textureCube(s_reflectcube, rtc).rgb;\n" +"#endif\n" "#ifdef CUBE\n" /*filter the colour by the cubemap projection*/ @@ -1979,6 +1995,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" + "}\n" "#endif\n" @@ -2130,21 +2147,22 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" -"Texture2D tx_base : register(t0);\n" -"Texture2D tx_bump : register(t1);\n" -"Texture2D tx_spec : register(t2);\n" -"TextureCube tx_cube : register(t3);\n" -"Texture2D tx_smap : register(t4);\n" -"Texture2D tx_lower : register(t5);\n" -"Texture2D tx_upper : register(t6);\n" +"Texture2D t_diffuse : register(t0);\n" +"Texture2D t_normalmap : register(t1);\n" +"Texture2D t_specular : register(t2);\n" +"Texture2D t_upper : register(t3);\n" +"Texture2D t_lower : register(t4);\n" +"Texture2D t_shadowmap : register(t5);\n" +"TextureCube t_projectionmap : register(t6);\n" + +"SamplerState s_diffuse : register(s0);\n" +"SamplerState s_normalmap : register(s1);\n" +"SamplerState s_specular : register(s2);\n" +"SamplerState s_upper : register(s3);\n" +"SamplerState s_lower : register(s4);\n" +"SamplerComparisonState s_shadowmap : register(s5);\n" +"SamplerState s_projectionmap : register(s6);\n" -"SamplerState ss_base : register(s0);\n" -"SamplerState ss_bump : register(s1);\n" -"SamplerState ss_spec : register(s2);\n" -"SamplerState ss_cube : register(s3);\n" -"SamplerComparisonState ss_smap : register(s4);\n" -"SamplerState ss_lower : register(s5);\n" -"SamplerState ss_upper : register(s6);\n" "#ifdef PCF\n" "float3 ShadowmapCoord(float3 vtexprojcoord)\n" @@ -2201,9 +2219,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND // #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r -// #define dosamp(x,y) (tx_smap.Sample(ss_smap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z) -"#define dosamp(x,y) (tx_smap.SampleCmpLevelZero(ss_smap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z))\n" - +// #define dosamp(x,y) (t_shadowmap.Sample(s_shadowmap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z) +"#define dosamp(x,y) (t_shadowmap.SampleCmpLevelZero(s_shadowmap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z))\n" "float s = 0.0;\n" "#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" @@ -2215,7 +2232,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "s += dosamp(0.0, 0.0);\n" "s += dosamp(0.0, 1.0);\n" "s += dosamp(1.0, 0.0);\n" -"return s/5.0;\n" +"return s * (1.0/5.0);\n" "#else\n" "s += dosamp(-1.0, -1.0);\n" "s += dosamp(-1.0, 0.0);\n" @@ -2226,7 +2243,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "s += dosamp(1.0, -1.0);\n" "s += dosamp(1.0, 0.0);\n" "s += dosamp(1.0, 1.0);\n" -"return s/9.0;\n" +"return s * (1.0/9.0);\n" "#endif\n" "}\n" "#endif\n" @@ -2236,23 +2253,23 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "{\n" "float2 tc = inp.tc; //TODO: offsetmapping.\n" -"float4 base = tx_base.Sample(ss_base, tc);\n" +"float4 base = t_diffuse.Sample(s_diffuse, tc);\n" "#ifdef BUMP\n" -"float4 bump = tx_bump.Sample(ss_bump, tc);\n" +"float4 bump = t_normalmap.Sample(s_normalmap, tc);\n" "bump.rgb = normalize(bump.rgb - 0.5);\n" "#else\n" "float4 bump = float4(0, 0, 1, 0);\n" "#endif\n" -"float4 spec = tx_spec.Sample(ss_spec, tc);\n" +"float4 spec = t_specular.Sample(s_specular, tc);\n" "#ifdef CUBE\n" -"float4 cubemap = tx_cube.Sample(ss_cube, inp.vtexprojcoord);\n" +"float4 cubemap = t_projectionmap.Sample(s_projectionmap, inp.vtexprojcoord);\n" "#endif\n" "#ifdef LOWER\n" -"float4 lower = tx_lower.Sample(ss_lower, tc);\n" +"float4 lower = t_lower.Sample(s_lower, tc);\n" "base += lower;\n" "#endif\n" "#ifdef UPPER\n" -"float4 upper = tx_upper.Sample(ss_upper, tc);\n" +"float4 upper = t_upper.Sample(s_upper, tc);\n" "base += upper;\n" "#endif\n" diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 0d431efb3..631cae5ec 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -32,7 +32,7 @@ lights are then added over the top based upon the diffusemap, bumpmap and specul typedef void (shader_gen_t)(const char *name, shader_t*, const void *args); #define SHADER_TMU_MAX 16 -#define SHADER_PASS_MAX 8 +#define SHADER_PASS_MAX 16 #define SHADER_MAX_TC_MODS 8 #define SHADER_DEFORM_MAX 8 #define SHADER_MAX_ANIMFRAMES 16 @@ -256,6 +256,8 @@ typedef struct shaderpass_s { T_GEN_LOWEROVERLAY, //texture's default team colour T_GEN_FULLBRIGHT, //texture's default fullbright overlay T_GEN_PALETTED, //texture's original paletted data (8bit) + T_GEN_REFLECTCUBE, //dpreflectcube + T_GEN_REFLECTMASK, //dpreflectcube mask T_GEN_CURRENTRENDER,//copy the current screen to a texture, and draw that @@ -316,7 +318,7 @@ enum{ PERMUTATION_BUMPMAP = 1, PERMUTATION_FULLBRIGHT = 2, PERMUTATION_UPPERLOWER = 4, - PERMUTATION_DELUXE = 8, + PERMUTATION_REFLECTCUBEMASK = 8, PERMUTATION_SKELETAL = 16, PERMUTATION_FOG = 32, PERMUTATION_FRAMEBLEND = 64, @@ -489,7 +491,6 @@ enum struct shader_s { char name[MAX_QPATH]; - char mapname[MAX_QPATH]; enum { SUF_NONE = 0, SUF_LIGHTMAP = 1<<0, //$lightmap passes are valid. otherwise collapsed to an rgbgen @@ -499,7 +500,9 @@ struct shader_s int width; //when used as an image, this is the logical 'width' of the image. FIXME. int height; int numpasses; - texnums_t defaulttextures; + unsigned int numdefaulttextures; //0 is effectively 1. + float defaulttextures_fps; + texnums_t *defaulttextures; //must always have at least one entry. multiple will only appear if the diffuse texture was animmapped. struct shader_s *next; int id; //end of shared fields. @@ -694,7 +697,7 @@ void GLBE_Init(void); void GLBE_Shutdown(void); void GLBE_SelectMode(backendmode_t mode); void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); -void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsigned int beflags); void GLBE_SubmitBatch(batch_t *batch); batch_t *GLBE_GetTempBatch(void); void GLBE_GenBrushModelVBO(model_t *mod); @@ -724,7 +727,7 @@ void D3D9BE_Init(void); void D3D9BE_Shutdown(void); void D3D9BE_SelectMode(backendmode_t mode); void D3D9BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); -void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D9BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsigned int beflags); void D3D9BE_SubmitBatch(batch_t *batch); batch_t *D3D9BE_GetTempBatch(void); void D3D9BE_GenBrushModelVBO(model_t *mod); @@ -748,7 +751,7 @@ void D3D11BE_Init(void); void D3D11BE_Shutdown(void); void D3D11BE_SelectMode(backendmode_t mode); void D3D11BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); -void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags); +void D3D11BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, unsigned int beflags); void D3D11BE_SubmitBatch(batch_t *batch); batch_t *D3D11BE_GetTempBatch(void); void D3D11BE_GenBrushModelVBO(model_t *mod); diff --git a/engine/partcfgs/q2part.cfg b/engine/partcfgs/q2part.cfg index 1e0caf930..84933c612 100644 --- a/engine/partcfgs/q2part.cfg +++ b/engine/partcfgs/q2part.cfg @@ -15,6 +15,118 @@ r_part pe_default scalefactor 0.8 } +r_part te_splashsparks +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xe0 +} +r_part teq2_sparks +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 6 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xe0 +} +r_part te_splashbluewater +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xb0 +} +r_part te_splashbrownwater +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0x50 +} +r_part te_splashslime +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xd0 +} +r_part te_splashlava +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xe0 +} +r_part te_splashblood +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + count 1 + scale 1 + alpha 1 + die 0.3 0.8 + randomvel 20 + orgadd 0 31 + spawnorg 4 + gravity 40 + scalefactor 0.8 + colorindex 0xe8 +} + + +//teq2_shield_sparks +//teq2_screen_sparks +//teq2_laser_sparks + + r_part q2_smoke { @@ -126,6 +238,22 @@ r_part TR_BLASTERTRAIL colorindex 0xe0 } + +r_part teq2_bubbletrail +{ + /*blue spiral*/ + texture "classicparticle" + tcoords 0 0 16 16 32 + scale 0.5 + alpha 1 + scalefactor 0.8 + step 32 + spawnorg 2 + spawnvel 5 + die 1 1.2 + colorindex 4 7 +} + r_part TR_RAILTRAIL { /*blue spiral*/ diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index b505d08fc..addfc2006 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern int total_loading_size, current_loading_size, loading_stage; char *T_GetString(int num); +void SVQ2_Ents_Shutdown(void); #define Q2EDICT_NUM(i) (q2edict_t*)((char *)ge->edicts+(i)*ge->edict_size) server_static_t svs; // persistant server info @@ -597,6 +598,7 @@ void SV_UnspawnServer (void) //terminate the running server. #endif #ifdef Q2SERVER SVQ2_ShutdownGameProgs(); + SVQ2_Ents_Shutdown(); #endif #ifdef HLSERVER SVHL_ShutdownGame(); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index bd871cd81..6563a451b 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -478,6 +478,10 @@ void SV_DropClient (client_t *drop) #ifdef SVCHAT SV_WipeChat(drop); #endif + + if (sv.world.worldmodel->loadstate != MLS_LOADED) + Con_Printf(CON_WARNING "Warning: not notifying gamecode about client disconnection due to invalid worldmodel\n"); + else switch(svs.gametype) { case GT_MAX: diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index 2785bd837..d0fd1eddf 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -694,7 +694,6 @@ int main(int argc, char *argv[]) memset (&parms, 0, sizeof(parms)); COM_InitArgv (argc, (const char **)argv); - TL_InitLanguages(); parms.argc = com_argc; parms.argv = com_argv; @@ -713,6 +712,7 @@ int main(int argc, char *argv[]) #endif parms.basedir = "./"; + TL_InitLanguages(parms.basedir); SV_Init (&parms); diff --git a/engine/server/sv_sys_win.c b/engine/server/sv_sys_win.c index fd1762828..b9a80d03e 100644 --- a/engine/server/sv_sys_win.c +++ b/engine/server/sv_sys_win.c @@ -1369,8 +1369,6 @@ void StartQuakeServer(void) memset(&parms, 0, sizeof(parms)); - TL_InitLanguages(); - parms.argc = com_argc; parms.argv = com_argv; @@ -1380,6 +1378,8 @@ void StartQuakeServer(void) parms.basedir = "./"; + TL_InitLanguages(parms.basedir); + SV_Init (&parms); // run one frame immediately for first heartbeat diff --git a/engine/server/svq2_ents.c b/engine/server/svq2_ents.c index 4473dba30..c8917f1b3 100644 --- a/engine/server/svq2_ents.c +++ b/engine/server/svq2_ents.c @@ -777,6 +777,15 @@ void SVQ2_Ents_Init(void) svs_client_entities = Z_Malloc (sizeof(entity_state_t)*svs_num_client_entities); } } +void SVQ2_Ents_Shutdown(void) +{ + if (svs_client_entities) + { + Z_Free(svs_client_entities); + svs_client_entities = NULL; + svs_num_client_entities = 0; + } +} #endif #endif diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c index 9a609ac4f..fabc4b32c 100644 --- a/engine/shaders/generatebuiltinsl.c +++ b/engine/shaders/generatebuiltinsl.c @@ -80,7 +80,7 @@ struct shadertype_s } shadertype[] = { {"glsl/%s.glsl", "GLQUAKE", "QR_OPENGL", 110}, //gl2+ - {"gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles + //{"gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles {"hlsl9/%s.hlsl", "D3D9QUAKE", "QR_DIRECT3D9", 9}, //d3d9 {"hlsl11/%s.hlsl", "D3D11QUAKE", "QR_DIRECT3D11", 11}, //d3d11 }; diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl index b72f5b5b2..625842d35 100644 --- a/engine/shaders/glsl/defaultwall.glsl +++ b/engine/shaders/glsl/defaultwall.glsl @@ -4,6 +4,7 @@ !!permu LIGHTSTYLED !!permu BUMP !!permu SPECULAR +!!permu REFLECTCUBEMASK !!cvarf r_glsl_offsetmapping_scale !!cvarf gl_specular @@ -13,10 +14,14 @@ //note that the '286' preset uses drawflat_walls instead. #include "sys/fog.h" -#if defined(OFFSETMAPPING) || defined(SPECULAR) +#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) varying vec3 eyevector; #endif +#ifdef REFLECTCUBEMASK +varying mat3 invsurface; +#endif + varying vec2 tc; #ifdef LIGHTSTYLED //we could use an offset, but that would still need to be per-surface which would break batches @@ -29,11 +34,16 @@ varying vec2 lm0; #ifdef VERTEX_SHADER void main () { -#if defined(OFFSETMAPPING) || defined(SPECULAR) +#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) vec3 eyeminusvertex = e_eyepos - v_position.xyz; eyevector.x = dot(eyeminusvertex, v_svector.xyz); eyevector.y = dot(eyeminusvertex, v_tvector.xyz); eyevector.z = dot(eyeminusvertex, v_normal.xyz); +#endif +#ifdef REFLECTCUBEMASK + invsurface[0] = v_svector; + invsurface[1] = v_tvector; + invsurface[2] = v_normal; #endif tc = v_texcoord; lm0 = v_lmcoord; @@ -79,9 +89,9 @@ void main () //yay, regular texture! gl_FragColor = texture2D(s_diffuse, tc); -#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR)) +#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK)) vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5); -#elif defined(SPECULAR) || defined(DELUXE) +#elif defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK) vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist. #endif @@ -127,6 +137,13 @@ void main () gl_FragColor.rgb += spec * specs.rgb; #endif +#ifdef REFLECTCUBEMASK + vec3 rtc = reflect(-eyevector, norm); + rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2]; + rtc = (m_model * vec4(rtc.xyz,0.0)).xyz; + gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb; +#endif + #ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant. lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1. float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated. @@ -144,7 +161,6 @@ void main () #endif #endif - //entity modifiers gl_FragColor = gl_FragColor * e_colourident; diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl index 15ff57c36..f844d5b36 100644 --- a/engine/shaders/glsl/rtlight.glsl +++ b/engine/shaders/glsl/rtlight.glsl @@ -3,6 +3,7 @@ !!permu SKELETAL !!permu UPPERLOWER !!permu FOG +!!permu REFLECTCUBEMASK !!cvarf r_glsl_offsetmapping_scale !!cvardf r_glsl_pcf @@ -50,9 +51,13 @@ varying vec2 tcbase; varying vec3 lightvector; -#if defined(SPECULAR) || defined(OFFSETMAPPING) +#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) varying vec3 eyevector; #endif +#ifdef REFLECTCUBEMASK +varying mat3 invsurface; +uniform mat4 m_model; +#endif #if defined(PCF) || defined(CUBE) || defined(SPOT) varying vec4 vtexprojcoord; #endif @@ -65,7 +70,7 @@ uniform mat4 l_cubematrix; #include "sys/skeletal.h" uniform vec3 l_lightposition; attribute vec2 v_texcoord; -#if defined(SPECULAR) || defined(OFFSETMAPPING) +#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) uniform vec3 e_eyepos; #endif void main () @@ -83,12 +88,17 @@ void main () lightvector.y = dot(lightminusvertex, t.xyz); lightvector.z = dot(lightminusvertex, n.xyz); #endif -#if defined(SPECULAR)||defined(OFFSETMAPPING) +#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) vec3 eyeminusvertex = e_eyepos - w.xyz; eyevector.x = dot(eyeminusvertex, s.xyz); eyevector.y = dot(eyeminusvertex, t.xyz); eyevector.z = dot(eyeminusvertex, n.xyz); #endif +#ifdef REFLECTCUBEMASK + invsurface[0] = v_svector; + invsurface[1] = v_tvector; + invsurface[2] = v_normal; +#endif #if defined(PCF) || defined(SPOT) || defined(CUBE) //for texture projections/shadowmapping on dlights vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0)); @@ -103,7 +113,7 @@ void main () #include "sys/fog.h" uniform sampler2D s_t0; //diffuse -#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) +#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK) uniform sampler2D s_t1; //normalmap #endif #ifdef SPECULAR @@ -132,6 +142,11 @@ uniform sampler2D s_t6; //shirt colours uniform vec3 e_uppercolour; #endif +#ifdef REFLECTCUBEMASK +uniform sampler2D s_reflectmask; +uniform samplerCube s_reflectcube; +#endif + uniform float l_lightradius; uniform vec3 l_lightcolour; @@ -260,8 +275,10 @@ void main () vec4 lc = texture2D(s_t5, tcbase); bases.rgb += lc.rgb*e_lowercolour*lc.a; #endif -#if defined(BUMP) || defined(SPECULAR) +#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK) vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5); +#elif defined(REFLECTCUBEMASK) + vec3 bumps = vec3(0.0,0.0,1.0); #endif #ifdef SPECULAR vec4 specs = texture2D(s_t2, tcbase); @@ -289,7 +306,12 @@ void main () diff += l_lightcolourscale.z * spec * specs.rgb; #endif - +#ifdef REFLECTCUBEMASK + vec3 rtc = reflect(-eyevector, bumps); + rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2]; + rtc = (m_model * vec4(rtc.xyz,0.0)).xyz; + diff += texture2D(s_reflectmask, tcbase).rgb * textureCube(s_reflectcube, rtc).rgb; +#endif #ifdef CUBE /*filter the colour by the cubemap projection*/ @@ -315,6 +337,7 @@ void main () #endif gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour); + } #endif diff --git a/engine/shaders/hlsl11/default2d.hlsl b/engine/shaders/hlsl11/default2d.hlsl index 43707b5dc..6c6bcd2c6 100644 --- a/engine/shaders/hlsl11/default2d.hlsl +++ b/engine/shaders/hlsl11/default2d.hlsl @@ -17,9 +17,7 @@ struct v2f v2f main (a2v inp) { v2f outp; - outp.pos = mul(m_model, inp.pos); - outp.pos = mul(m_view, outp.pos); - outp.pos = mul(m_projection, outp.pos); + outp.pos = mul(m_projection, inp.pos); outp.tc = inp.tc; outp.vcol = inp.vcol; return outp; @@ -27,10 +25,10 @@ struct v2f #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture; - SamplerState SampleType; + Texture2D t_t0; + SamplerState s_t0; float4 main (v2f inp) : SV_TARGET { - return shaderTexture.Sample(SampleType, inp.tc) * inp.vcol; + return t_t0.Sample(s_t0, inp.tc) * inp.vcol; } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/defaultskin.hlsl b/engine/shaders/hlsl11/defaultskin.hlsl index 10c333746..b5091395b 100644 --- a/engine/shaders/hlsl11/defaultskin.hlsl +++ b/engine/shaders/hlsl11/defaultskin.hlsl @@ -30,14 +30,22 @@ struct v2f } #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture[4]; //diffuse, lower, upper, fullbright + Texture2D t_diffuse : register(t0); +#ifdef UPPER + Texture2D t_upper : register(t1); + Texture2D t_lower : register(t2); + Texture2D t_fullbright : register(t3); +#else + Texture2D t_fullbright : register(t1); +#endif + SamplerState SampleType; //uniform vec4 e_colourident; float4 main (v2f inp) : SV_TARGET { float4 col; - col = shaderTexture[0].Sample(SampleType, inp.tc); + col = t_diffuse.Sample(SampleType, inp.tc); #ifdef MASK #ifndef MASKOP @@ -49,18 +57,18 @@ struct v2f #endif #ifdef UPPER - float4 uc = shaderTexture[2].Sample(SampleType, inp.tc); - col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a); + float4 uc = t_upper.Sample(SampleType, inp.tc); + col.rgb = lerp(col.rgb, uc.rgb*e_uppercolour, uc.a); #endif #ifdef LOWER - float4 lc = shaderTexture[1].Sample(SampleType, inp.tc); - col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a); + float4 lc = t_lower.Sample(SampleType, inp.tc); + col.rgb = lerp(col.rgb, lc.rgb*e_lowercolour, lc.a); #endif col.rgb *= inp.light; -#ifdef FULLBRIGHT - float4 fb = shaderTexture[3].Sample(SampleType, inp.tc); - col.rgb = mix(col.rgb, fb.rgb, fb.a); -#endif +//#ifdef FULLBRIGHT + float4 fb = t_fullbright.Sample(SampleType, inp.tc); + col.rgb = lerp(col.rgb, fb.rgb, fb.a); +//#endif return col; // return fog4(col * e_colourident); } diff --git a/engine/shaders/hlsl11/defaultsky.hlsl b/engine/shaders/hlsl11/defaultsky.hlsl index fb8a29e71..041b9f0cb 100644 --- a/engine/shaders/hlsl11/defaultsky.hlsl +++ b/engine/shaders/hlsl11/defaultsky.hlsl @@ -29,8 +29,10 @@ struct v2f #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture[2]; - SamplerState SampleType; + Texture2D t_diffuse : register(t0); + Texture2D t_fullbright : register(t1); + SamplerState s_diffuse : register(s0); + SamplerState s_fullbright : register(s1); float4 main (v2f inp) : SV_TARGET { @@ -39,9 +41,9 @@ struct v2f dir.z *= 3.0; dir.xy /= 0.5*length(dir); tccoord = (dir.xy + e_time*0.03125); - float4 solid = shaderTexture[0].Sample(SampleType, tccoord); + float4 solid = t_diffuse.Sample(s_diffuse, tccoord); tccoord = (dir.xy + e_time*0.0625); - float4 clouds = shaderTexture[1].Sample(SampleType, tccoord); - return (solid*(1.0-clouds.a)) + (clouds.a*clouds); + float4 clouds = t_fullbright.Sample(s_fullbright, tccoord); + return lerp(solid, clouds, clouds.a); } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/defaultsprite.hlsl b/engine/shaders/hlsl11/defaultsprite.hlsl index e5c04d71f..69f0591e7 100644 --- a/engine/shaders/hlsl11/defaultsprite.hlsl +++ b/engine/shaders/hlsl11/defaultsprite.hlsl @@ -27,11 +27,11 @@ struct v2f #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture; - SamplerState SampleType; + Texture2D t_diffuse : register(t0); + SamplerState s_diffuse : register(s0); float4 main (v2f inp) : SV_TARGET { - float4 tex = shaderTexture.Sample(SampleType, inp.tc); + float4 tex = t_diffuse.Sample(s_diffuse, inp.tc); #ifdef MASK if (tex.a < float(MASK)) discard; diff --git a/engine/shaders/hlsl11/defaultwall.hlsl b/engine/shaders/hlsl11/defaultwall.hlsl index f8606d333..72d5fc973 100644 --- a/engine/shaders/hlsl11/defaultwall.hlsl +++ b/engine/shaders/hlsl11/defaultwall.hlsl @@ -26,23 +26,22 @@ struct v2f #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture[2]; - SamplerState SampleType[2]; + Texture2D t_lightmap : register(t2); + SamplerState s_lightmap : register(s2); + + Texture2D t_diffuse : register(s0); + SamplerState s_diffuse : register(s0); + + Texture2D t_fullbright : register(s1); + SamplerState s_fullbright : register(s1); float4 main (v2f inp) : SV_TARGET { - float4 tex = shaderTexture[0].Sample(SampleType[0], inp.tc); - float4 lm = shaderTexture[1].Sample(SampleType[1], inp.lmtc); - -#ifdef MASK -#ifndef MASKOP -#define MASKOP >= //drawn if (alpha OP ref) is true. -#endif - //support for alpha masking - if (!(tex.a MASKOP MASK)) - discard; -#endif - - return tex * lm.bgra; + float4 result; + result = t_diffuse.Sample(s_diffuse, inp.tc); + result.rgb *= t_lightmap.Sample(s_lightmap, inp.lmtc).bgr * e_lmscale[0].rgb; + float4 fb = t_fullbright.Sample(s_fullbright, inp.tc); + result.rgb += fb.rgb * fb.a;//lerp(result.rgb, fb.rgb, fb.a); + return result; } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/defaultwarp.hlsl b/engine/shaders/hlsl11/defaultwarp.hlsl index 90e95129e..2f7ff7b3b 100644 --- a/engine/shaders/hlsl11/defaultwarp.hlsl +++ b/engine/shaders/hlsl11/defaultwarp.hlsl @@ -28,14 +28,13 @@ struct v2f #ifdef FRAGMENT_SHADER // float cvar_r_wateralpha; // float e_time; -// sampler s_t0; - Texture2D shaderTexture; - SamplerState SampleType; + SamplerState s_diffuse; + Texture2D t_diffuse; float4 main (v2f inp) : SV_TARGET { float2 ntc; ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125; ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125; - return shaderTexture.Sample(SampleType, ntc); + return t_diffuse.Sample(s_diffuse, ntc); } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/depthonly.hlsl b/engine/shaders/hlsl11/depthonly.hlsl index 830a265ce..ef35e03bd 100644 --- a/engine/shaders/hlsl11/depthonly.hlsl +++ b/engine/shaders/hlsl11/depthonly.hlsl @@ -3,17 +3,11 @@ struct a2v { float4 pos: POSITION; - float3 normal: NORMAL; - #ifdef MASK - float4 tc: TEXCOORD0; - #endif }; struct v2f { + float3 col: TEXCOORD; float4 pos: SV_POSITION; - #ifdef MASK - float2 tc: TEXCOORD0; - #endif }; #include @@ -25,41 +19,22 @@ struct v2f outp.pos = mul(m_model, inp.pos); outp.pos = mul(m_view, outp.pos); outp.pos = mul(m_projection, outp.pos); - - #ifdef MASK - outp.tc = inp.tc.xy; - #endif - + outp.col = inp.pos.xyz - l_lightposition; return outp; } #endif + #ifdef FRAGMENT_SHADER - #ifdef MASK - Texture2D shaderTexture[1]; - SamplerState SampleType[1]; - #endif - - #if LEVEL < 1000 - //pre dx10 requires that we ALWAYS write to a target. - float4 main (v2f inp) : SV_TARGET + #if LEVEL < 0x10000 + //pre dx10 requires that we ALWAYS write to a target. + float4 main (v2f inp) : SV_TARGET + { + return float4(0, 0, 0, 1); + } #else - //but on 10, it'll write depth automatically and we don't care about colour. - void main (v2f inp) //dx10-level + //but on 10, it'll write depth automatically and we don't care about colour. + void main (v2f inp) + { + } #endif - { - - #ifdef MASK - float alpha = shaderTexture[0].Sample(SampleType[0], inp.tc).a; - #ifndef MASKOP - #define MASKOP >= //drawn if (alpha OP ref) is true. - #endif - //support for alpha masking - if (!(alpha MASKOP MASK)) - discard; - #endif - - #if LEVEL < 1000 - return float4(0, 0, 0, 1); - #endif - } #endif diff --git a/engine/shaders/hlsl11/drawflat_wall.hlsl b/engine/shaders/hlsl11/drawflat_wall.hlsl index 7a0839d5d..4db01a8e1 100644 --- a/engine/shaders/hlsl11/drawflat_wall.hlsl +++ b/engine/shaders/hlsl11/drawflat_wall.hlsl @@ -29,11 +29,11 @@ struct v2f #endif #ifdef FRAGMENT_SHADER - Texture2D shaderTexture; - SamplerState SampleType; + Texture2D t_lightmap : register(t0); + SamplerState s_lightmap : register(s0); float4 main (v2f inp) : SV_TARGET { - return inp.col * shaderTexture.Sample(SampleType, inp.lmtc); + return inp.col * t_lightmap.Sample(s_lightmap, inp.lmtc); } #endif \ No newline at end of file diff --git a/engine/shaders/hlsl11/rtlight.hlsl b/engine/shaders/hlsl11/rtlight.hlsl index 0326e1dea..2ef86c4f2 100644 --- a/engine/shaders/hlsl11/rtlight.hlsl +++ b/engine/shaders/hlsl11/rtlight.hlsl @@ -77,21 +77,22 @@ struct v2f #ifdef FRAGMENT_SHADER - Texture2D tx_base : register(t0); - Texture2D tx_bump : register(t1); - Texture2D tx_spec : register(t2); - TextureCube tx_cube : register(t3); - Texture2D tx_smap : register(t4); - Texture2D tx_lower : register(t5); - Texture2D tx_upper : register(t6); + Texture2D t_diffuse : register(t0); + Texture2D t_normalmap : register(t1); + Texture2D t_specular : register(t2); + Texture2D t_upper : register(t3); + Texture2D t_lower : register(t4); + Texture2D t_shadowmap : register(t5); + TextureCube t_projectionmap : register(t6); + + SamplerState s_diffuse : register(s0); + SamplerState s_normalmap : register(s1); + SamplerState s_specular : register(s2); + SamplerState s_upper : register(s3); + SamplerState s_lower : register(s4); + SamplerComparisonState s_shadowmap : register(s5); + SamplerState s_projectionmap : register(s6); - SamplerState ss_base : register(s0); - SamplerState ss_bump : register(s1); - SamplerState ss_spec : register(s2); - SamplerState ss_cube : register(s3); - SamplerComparisonState ss_smap : register(s4); - SamplerState ss_lower : register(s5); - SamplerState ss_upper : register(s6); #ifdef PCF float3 ShadowmapCoord(float3 vtexprojcoord) @@ -148,9 +149,8 @@ float ShadowmapFilter(float3 vtexprojcoord) // #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r -// #define dosamp(x,y) (tx_smap.Sample(ss_smap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z) - #define dosamp(x,y) (tx_smap.SampleCmpLevelZero(ss_smap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z)) - +// #define dosamp(x,y) (t_shadowmap.Sample(s_shadowmap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z) + #define dosamp(x,y) (t_shadowmap.SampleCmpLevelZero(s_shadowmap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z)) float s = 0.0; #if r_glsl_pcf >= 1 && r_glsl_pcf < 5 @@ -162,7 +162,7 @@ float ShadowmapFilter(float3 vtexprojcoord) s += dosamp(0.0, 0.0); s += dosamp(0.0, 1.0); s += dosamp(1.0, 0.0); - return s/5.0; + return s * (1.0/5.0); #else s += dosamp(-1.0, -1.0); s += dosamp(-1.0, 0.0); @@ -173,7 +173,7 @@ float ShadowmapFilter(float3 vtexprojcoord) s += dosamp(1.0, -1.0); s += dosamp(1.0, 0.0); s += dosamp(1.0, 1.0); - return s/9.0; + return s * (1.0/9.0); #endif } #endif @@ -183,23 +183,23 @@ float ShadowmapFilter(float3 vtexprojcoord) { float2 tc = inp.tc; //TODO: offsetmapping. - float4 base = tx_base.Sample(ss_base, tc); + float4 base = t_diffuse.Sample(s_diffuse, tc); #ifdef BUMP - float4 bump = tx_bump.Sample(ss_bump, tc); + float4 bump = t_normalmap.Sample(s_normalmap, tc); bump.rgb = normalize(bump.rgb - 0.5); #else float4 bump = float4(0, 0, 1, 0); #endif - float4 spec = tx_spec.Sample(ss_spec, tc); + float4 spec = t_specular.Sample(s_specular, tc); #ifdef CUBE - float4 cubemap = tx_cube.Sample(ss_cube, inp.vtexprojcoord); + float4 cubemap = t_projectionmap.Sample(s_projectionmap, inp.vtexprojcoord); #endif #ifdef LOWER - float4 lower = tx_lower.Sample(ss_lower, tc); + float4 lower = t_lower.Sample(s_lower, tc); base += lower; #endif #ifdef UPPER - float4 upper = tx_upper.Sample(ss_upper, tc); + float4 upper = t_upper.Sample(s_upper, tc); base += upper; #endif diff --git a/engine/sw/sw.h b/engine/sw/sw.h index 6d3e662c4..315863904 100644 --- a/engine/sw/sw.h +++ b/engine/sw/sw.h @@ -164,7 +164,7 @@ void SW_DestroyTexture (texid_t tex); void SWBE_SelectMode(backendmode_t mode); void SWBE_DrawMesh_List(shader_t *shader, int nummeshes, struct mesh_s **mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags); -void SWBE_DrawMesh_Single(shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags); +void SWBE_DrawMesh_Single(shader_t *shader, struct mesh_s *meshchain, struct vbo_s *vbo, unsigned int be_flags); void SWBE_SubmitBatch(struct batch_s *batch); struct batch_s *SWBE_GetTempBatch(void); void SWBE_DrawWorld(qboolean drawworld, qbyte *vis); diff --git a/engine/sw/sw_backend.c b/engine/sw/sw_backend.c index 9eb23f640..533f01da0 100644 --- a/engine/sw/sw_backend.c +++ b/engine/sw/sw_backend.c @@ -421,10 +421,18 @@ void SWBE_TransformVerticies(swvert_t *v, mesh_t *mesh) // v->colour[3] = mesh->colors4b_array[i][3]; } } -void SWBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags) +static void SWBE_DrawMesh_Internal(shader_t *shader, mesh_t *mesh, struct vbo_s *vbo, struct texnums_s *texnums, unsigned int be_flags) { wqcom_t *com; + if (!texnums) + { +// if (shader->numdefaulttextures) +// texnums = shader->defaulttextures + ; +// else + texnums = shader->defaulttextures; + } + shaderstate.curshader = shader; if (mesh->istrifan) @@ -456,16 +464,20 @@ void SWBE_DrawMesh_List(shader_t *shader, int nummeshes, struct mesh_s **mesh, s { while(nummeshes-->0) { - SWBE_DrawMesh_Single(shader, *mesh++, vbo, texnums, be_flags); + SWBE_DrawMesh_Internal(shader, *mesh++, vbo, texnums, be_flags); } } +void SWBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, struct vbo_s *vbo, unsigned int be_flags) +{ + SWBE_DrawMesh_Internal(shader, mesh, vbo, NULL, be_flags); +} void SWBE_SubmitBatch(struct batch_s *batch) { int m; SWBE_SelectEntity(batch->ent); for (m = 0; m < batch->meshes; m++) { - SWBE_DrawMesh_Single(batch->shader, batch->mesh[m], batch->vbo, batch->skin?batch->skin:&batch->shader->defaulttextures, batch->flags); + SWBE_DrawMesh_Internal(batch->shader, batch->mesh[m], batch->vbo, batch->skin, batch->flags); } } struct batch_s *SWBE_GetTempBatch(void) diff --git a/engine/web/sys_web.c b/engine/web/sys_web.c index 55a6357f5..0492302eb 100644 --- a/engine/web/sys_web.c +++ b/engine/web/sys_web.c @@ -202,7 +202,7 @@ int QDECL main(int argc, char **argv) COM_InitArgv (parms.argc, parms.argv); - TL_InitLanguages(); + TL_InitLanguages(""); Sys_Printf ("Host_Init\n"); Host_Init (&parms);