diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 74f4fa340..062fcb39a 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1075,7 +1075,6 @@ set (FASTMATH_SOURCES ${FASTMATH_SOURCES}) set (PCH_SOURCES glbackend/glbackend.cpp - glbackend/gl_palmanager.cpp glbackend/gl_texture.cpp thirdparty/src/md4.cpp @@ -1086,7 +1085,6 @@ set (PCH_SOURCES build/src/engine.cpp build/src/mdsprite.cpp build/src/polymost.cpp - build/src/voxmodel.cpp core/movie/playmve.cpp core/automap.cpp @@ -1134,6 +1132,8 @@ set (PCH_SOURCES core/rendering/hw_entrypoint.cpp core/rendering/hw_models.cpp + core/rendering/hw_voxels.cpp + core/rendering/hw_palmanager.cpp core/rendering/scene/hw_clipper.cpp core/rendering/scene/hw_walls.cpp core/rendering/scene/hw_flats.cpp diff --git a/source/build/include/build.h b/source/build/include/build.h index 813165c23..bab82520d 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -200,7 +200,7 @@ enum { PALETTE_TRANSLUC = 1<<2, }; -EXTERN int32_t g_visibility, parallaxvisibility; +EXTERN int32_t g_visibility; // blendtable[1] to blendtable[numalphatabs] are considered to be // alpha-blending tables: @@ -269,12 +269,6 @@ extern FixedBitArray gotsector; extern uint32_t drawlinepat; -extern int32_t novoxmips; - -extern int16_t tiletovox[MAXTILES]; -extern int32_t voxscale[MAXVOXELS]; -extern char g_haveVoxels; - extern uint8_t globalr, globalg, globalb; enum { @@ -362,10 +356,6 @@ void engineLoadBoard(const char *filename, int flags, vec3_t *dapos, int16_t *da void loadMapBackup(const char* filename); void G_LoadMapHack(const char* filename, const unsigned char*); -int32_t qloadkvx(int32_t voxindex, const char *filename); -void vox_undefine(int32_t const); -void vox_deinit(); - void videoSetCorrectedAspect(); void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2); void renderSetAspect(int32_t daxrange, int32_t daaspect); @@ -448,7 +438,6 @@ inline int32_t ksqrt(uint32_t num) } int32_t getangle(int32_t xvect, int32_t yvect); -fixed_t gethiq16angle(int32_t xvect, int32_t yvect); inline constexpr uint32_t uhypsq(int32_t const dx, int32_t const dy) { @@ -598,7 +587,6 @@ int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, f EXTERN int32_t nextvoxid; EXTERN int8_t voxreserve[(MAXVOXELS+7)>>3]; -EXTERN int8_t voxrotate[(MAXVOXELS+7)>>3]; #ifdef USE_OPENGL // TODO: dynamically allocate this @@ -628,13 +616,7 @@ inline int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal) } #endif // defined USE_OPENGL -inline int tilehasmodelorvoxel(int const tilenume, int pal) -{ - UNREFERENCED_PARAMETER(pal); - return - (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || - (r_voxels && tiletovox[tilenume] != -1); -} +int tilehasmodelorvoxel(int const tilenume, int pal); int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal); @@ -647,7 +629,7 @@ int32_t md_definehud (int32_t modelid, int32_t tilex, vec3f_t add, int32_t md_undefinetile(int32_t tile); int32_t md_undefinemodel(int32_t modelid); -int32_t loaddefinitionsfile(const char *fn, bool loadadds = false); +int32_t loaddefinitionsfile(const char *fn, bool loadadds = false, bool cumulative = false); #ifdef USE_OPENGL # include "polymost.h" @@ -735,9 +717,6 @@ extern int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum); extern int32_t(*deletesprite_replace)(int16_t spritenum); extern int32_t(*changespritesect_replace)(int16_t spritenum, int16_t newsectnum); extern int32_t(*changespritestat_replace)(int16_t spritenum, int16_t newstatnum); -#ifdef USE_OPENGL -extern void(*PolymostProcessVoxels_Callback)(void); -#endif // Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did. // Gonna be fun to globally replace these to finally lift the limit this imposes on map size. diff --git a/source/build/include/cstat.h b/source/build/include/cstat.h deleted file mode 100644 index 17824c3c2..000000000 --- a/source/build/include/cstat.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -// nobody uses these. What's so cool about naked numbers? :( -#if 0 -// system defines for status bits -#define CEILING_STAT_PLAX BIT(0) -#define CEILING_STAT_SLOPE BIT(1) -#define CEILING_STAT_SWAPXY BIT(2) -#define CEILING_STAT_SMOOSH BIT(3) -#define CEILING_STAT_XFLIP BIT(4) -#define CEILING_STAT_YFLIP BIT(5) -#define CEILING_STAT_RELATIVE BIT(6) -#define CEILING_STAT_TYPE_MASK (BIT(7)|BIT(8)) -#define CEILING_STAT_MASKED BIT(7) -#define CEILING_STAT_TRANS BIT(8) -#define CEILING_STAT_TRANS_FLIP (BIT(7)|BIT(8)) -#define CEILING_STAT_FAF_BLOCK_HITSCAN BIT(15) - -#define FLOOR_STAT_PLAX BIT(0) -#define FLOOR_STAT_SLOPE BIT(1) -#define FLOOR_STAT_SWAPXY BIT(2) -#define FLOOR_STAT_SMOOSH BIT(3) -#define FLOOR_STAT_XFLIP BIT(4) -#define FLOOR_STAT_YFLIP BIT(5) -#define FLOOR_STAT_RELATIVE BIT(6) -#define FLOOR_STAT_TYPE_MASK (BIT(7)|BIT(8)) -#define FLOOR_STAT_MASKED BIT(7) -#define FLOOR_STAT_TRANS BIT(8) -#define FLOOR_STAT_TRANS_FLIP (BIT(7)|BIT(8)) -#define FLOOR_STAT_FAF_BLOCK_HITSCAN BIT(15) - -#define CSTAT_WALL_BLOCK BIT(0) -#define CSTAT_WALL_BOTTOM_SWAP BIT(1) -#define CSTAT_WALL_ALIGN_BOTTOM BIT(2) -#define CSTAT_WALL_XFLIP BIT(3) -#define CSTAT_WALL_MASKED BIT(4) -#define CSTAT_WALL_1WAY BIT(5) -#define CSTAT_WALL_BLOCK_HITSCAN BIT(6) -#define CSTAT_WALL_TRANSLUCENT BIT(7) -#define CSTAT_WALL_YFLIP BIT(8) -#define CSTAT_WALL_TRANS_FLIP BIT(9) -#define CSTAT_WALL_BLOCK_ACTOR (BIT(14)) // my def -#define CSTAT_WALL_WARP_HITSCAN (BIT(15)) // my def -#endif diff --git a/source/build/include/mdsprite.h b/source/build/include/mdsprite.h index fd27cf90d..f2cfa4415 100644 --- a/source/build/include/mdsprite.h +++ b/source/build/include/mdsprite.h @@ -177,25 +177,6 @@ struct md3model_t : public idmodel_t */ }; -#define VOXBORDWIDTH 1 //use 0 to save memory, but has texture artifacts; 1 looks better... -#define VOXUSECHAR 0 - -#if (VOXUSECHAR != 0) -typedef struct { uint8_t x, y, z, u, v; } vert_t; -#else -typedef struct { uint16_t x, y, z, u, v; } vert_t; -#endif - -typedef struct { vert_t v[4]; } voxrect_t; - -struct voxmodel_t : public mdmodel_t -{ - FVoxelModel* model = nullptr; - vec3_t siz; - vec3f_t piv; - int32_t is8bit; -}; - EXTERN mdmodel_t **models; FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact); @@ -206,11 +187,6 @@ EXTERN void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f EXTERN int32_t mdpause; EXTERN int32_t nextmodelid; -EXTERN voxmodel_t *voxmodels[MAXVOXELS]; - -void voxfree(voxmodel_t *m); -voxmodel_t *voxload(int lumpnum); -int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr, bool rotate); #endif // defined USE_OPENGL diff --git a/source/build/include/polymost.h b/source/build/include/polymost.h index 2bbdbb637..e1e9a15f3 100644 --- a/source/build/include/polymost.h +++ b/source/build/include/polymost.h @@ -32,7 +32,6 @@ void polymost_deletesprite(int num); int32_t polymost_maskWallHasTranslucency(walltype const * const wall); int32_t polymost_spriteHasTranslucency(spritetype const * const tspr); -int32_t polymost_spriteIsModelOrVoxel(spritetype const * const tspr); void polymost_glreset(void); void polymost_scansector(int32_t sectnum); diff --git a/source/build/include/scriptfile.h b/source/build/include/scriptfile.h index c7aaf4fa8..5b742cd29 100644 --- a/source/build/include/scriptfile.h +++ b/source/build/include/scriptfile.h @@ -113,12 +113,6 @@ inline void scriptfile_close(scriptfile *sf) delete sf; } -inline int32_t scriptfile_addsymbolvalue(scriptfile *sf, char const *name, int32_t val) -{ - sf->AddSymbol(name, val); - return 1; -} - typedef struct { const char *text; diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 0ce87e508..dc8300d2e 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -17,11 +17,8 @@ #include "gamecontrol.h" #include "palettecontainer.h" #include "mapinfo.h" - -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); -int tileSetSkybox(int picnum, int palnum, const char** facenames, int flags); -void tileRemoveReplacement(int num); - +#include "hw_voxels.h" +#include "parsefuncs.h" int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens) { @@ -39,68 +36,6 @@ int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens) } void AddUserMapHack(usermaphack_t&); -#if 0 -// For later -{ -if (sc.Compare("music")) -{ - FString id, mus; - sc.MustGetToken('{'); - while (!sc.CheckToken('}')) - { - sc.MustGetToken(TK_Identifier); - if (sc.Compare("id")) - { - sc.MustGetString(); - id = sc.String; - } - else if (sc.Compare("file")) - { - sc.MustGetString(); - mus = sc.String; - } - } - - if (!SetMusicForMap(id, mus, true)) - { - sc.ScriptError("Map %s not found in music definition", id.GetChars()); - } - - char* tokenPtr = pScript->ltextptr; - char* musicID = NULL; - char* fileName = NULL; - char* musicEnd; - - if (scriptfile_getbraces(pScript, &musicEnd)) - break; - - while (pScript->textptr < musicEnd) - { - switch (getatoken(pScript, soundTokens, countof(soundTokens))) - { - case T_ID: scriptfile_getstring(pScript, &musicID); break; - case T_FILE: scriptfile_getstring(pScript, &fileName); break; - } - } - - if (!firstPass) - { - if (musicID == NULL) - { - pos.Message(MSG_ERROR, "missing ID for music definition\n"); - break; - } - - if (fileName == NULL || fileSystem.FileExists(fileName)) - break; - - if (S_DefineMusic(musicID, fileName) == -1) - pos.Message(MSG_ERROR, "invalid music ID"); - } - -} -} -#endif enum scripttoken_t { @@ -388,186 +323,44 @@ static int32_t defsparser(scriptfile *script) break; } case T_INCLUDEDEFAULT: - { defsparser_include(G_DefaultDefFile(), script, &pos); break; - } - case T_DEFINE: - { - FString name; - int32_t number; - - if (scriptfile_getstring(script,&name)) break; - if (scriptfile_getsymbol(script,&number)) break; - - if (scriptfile_addsymbolvalue(script, name,number) < 0) - pos.Message(MSG_WARNING, "Warning: Symbol %s was NOT redefined to %d", name.GetChars(),number); - break; - } - - // OLD (DEPRECATED) DEFINITION SYNTAX - case T_DEFINETEXTURE: - { - int32_t tile,pal,fnoo; - FString fn; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getnumber(script,&fnoo)) break; //x-center - if (scriptfile_getnumber(script,&fnoo)) break; //y-center - if (scriptfile_getnumber(script,&fnoo)) break; //x-size - if (scriptfile_getnumber(script,&fnoo)) break; //y-size - if (scriptfile_getstring(script,&fn)) break; - - if (!fileSystem.FileExists(fn)) - break; - - tileSetHightileReplacement(tile,pal,fn,-1.0,1.0,1.0,1.0,1.0,0); - } - break; - case T_DEFINESKYBOX: - { - int32_t tile,pal,i; - FString fn[6]; - int happy = 1; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getsymbol(script,&i)) break; //future expansion - for (i=0; i<6; i++) - { - if (scriptfile_getstring(script,&fn[i])) break; //grab the 6 faces - - if (!fileSystem.FileExists(fn[i])) - happy = 0; - } - if (i < 6 || !happy) break; - tileSetSkybox(tile, pal, (const char **)fn, 0); - } - break; - case T_DEFINETINT: - { - int32_t pal, r,g,b,f; - - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - if (scriptfile_getnumber(script,&f)) break; //effects - lookups.setPaletteTint(pal,r,g,b,0,0,0,f); - } - break; - case T_ALPHAHACK: - { - int32_t tile; - double alpha; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getdouble(script,&alpha)) break; - if ((uint32_t)tile < MAXTILES) - TileFiles.tiledata[tile].texture->alphaThreshold = (float)alpha; - } - break; - case T_ALPHAHACKRANGE: - { - int32_t tilenume1,tilenume2; - double alpha; - - if (scriptfile_getsymbol(script,&tilenume1)) break; - if (scriptfile_getsymbol(script,&tilenume2)) break; - if (scriptfile_getdouble(script,&alpha)) break; - - if (check_tile_range("alphahackrange", &tilenume1, &tilenume2, script, pos)) - break; - - for (int i=tilenume1; i<=tilenume2; i++) - TileFiles.tiledata[i].texture->alphaThreshold = (float)alpha; - } - break; - case T_SPRITECOL: - { - int32_t tile,col,col2; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&col2)) break; - } - break; - case T_2DCOL: - { - int32_t col,b,g,r; - - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - - if ((unsigned)col < 256) - { - } - } - break; - case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() - { - int32_t col, idx, idxend; - - if (scriptfile_getnumber(script,&col)) break; - if (scriptfile_getnumber(script,&idx)) break; - if (scriptfile_getnumber(script,&idxend)) break; - - } - break; - case T_FOGPAL: - { - int32_t p,r,g,b; - - if (scriptfile_getsymbol(script,&p)) break; - if (scriptfile_getnumber(script,&r)) break; - if (scriptfile_getnumber(script,&g)) break; - if (scriptfile_getnumber(script,&b)) break; - - r = clamp(r, 0, 63); - g = clamp(g, 0, 63); - b = clamp(b, 0, 63); - - lookups.makeTable(p, NULL, r<<2, g<<2, b<<2, 1); - } - break; - case T_NOFLOORPALRANGE: - { - int32_t b,e,i; - - if (scriptfile_getsymbol(script,&b)) break; - if (scriptfile_getsymbol(script,&e)) break; - - b = max(b, 1); - e = min(e, MAXPALOOKUPS-1); - - for (i = b; i <= e; i++) - lookups.tables[i].noFloorPal = true; - } - break; case T_LOADGRP: - { - scriptfile_getstring(script,nullptr); -#if 0 - if (!scriptfile_getstring(pScript, &fileName) && firstPass) - { - fileSystem.AddAdditionalFile(fileName); - } -#endif - } - break; case T_CACHESIZE: - { - int32_t j; - - if (scriptfile_getnumber(script,&j)) break; - } - break; case T_SHADEFACTOR: - //scriptfile_getnumber(script, &realmaxshade); - //frealmaxshade = (float)realmaxshade; + case T_GLOBALGAMEFLAGS: + parseSkip<1>(*script, pos); + break; + case T_SPRITECOL: + case T_2DCOLIDXRANGE: // NOTE: takes precedence over 2dcol, see InitCustomColors() + parseSkip<3>(*script, pos); + break; + case T_2DCOL: + parseSkip<4>(*script, pos); + break; + case T_DEFINE: + parseDefine(*script, pos); + break; + case T_DEFINETEXTURE: + parseDefineTexture(*script, pos); + break; + case T_DEFINESKYBOX: + parseDefineSkybox(*script, pos); + break; + case T_DEFINETINT: + parseDefineTint(*script, pos); + break; + case T_ALPHAHACK: + parseAlphahack(*script, pos); + break; + case T_ALPHAHACKRANGE: + parseAlphahackRange(*script, pos); + break; + case T_FOGPAL: + parseFogpal(*script, pos); + break; + case T_NOFLOORPALRANGE: + parseNoFloorpalRange(*script, pos); break; case T_ARTFILE: { @@ -609,59 +402,17 @@ static int32_t defsparser(scriptfile *script) } break; case T_SETUPTILE: - { - int tile, tmp; - - if (scriptfile_getsymbol(script,&tile)) break; - if (check_tile("setuptile", tile, script, pos)) - break; - auto& tiled = TileFiles.tiledata[tile]; - if (scriptfile_getsymbol(script,&tmp)) break; // XXX - tiled.h_xsize = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_ysize = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_xoffs = tmp; - if (scriptfile_getsymbol(script,&tmp)) break; - tiled.h_yoffs = tmp; + parseSetupTile(*script, pos); break; - } + case T_SETUPTILERANGE: - { - int tile1,tile2,xsiz,ysiz,xoffs,yoffs,i; - - if (scriptfile_getsymbol(script,&tile1)) break; - if (scriptfile_getsymbol(script,&tile2)) break; - if (scriptfile_getnumber(script,&xsiz)) break; - if (scriptfile_getnumber(script,&ysiz)) break; - if (scriptfile_getsymbol(script,&xoffs)) break; - if (scriptfile_getsymbol(script,&yoffs)) break; - - if (check_tile_range("setuptilerange", &tile1, &tile2, script, pos)) - break; - - for (i=tile1; i<=tile2; i++) - { - auto& tiled = TileFiles.tiledata[i]; - - tiled.h_xsize = xsiz; - tiled.h_ysize = ysiz; - tiled.h_xoffs = xoffs; - tiled.h_yoffs = yoffs; - } - + parseSetupTileRange(*script, pos); break; - } + case T_ANIMTILERANGE: - { - SetAnim set; - if (scriptfile_getsymbol(script,&set.tile1)) break; - if (scriptfile_getsymbol(script,&set.tile2)) break; - if (scriptfile_getsymbol(script,&set.speed)) break; - if (scriptfile_getsymbol(script,&set.type)) break; - processSetAnim("animtilerange", pos, set); + parseAnimTileRange(*script, pos); break; - } + case T_TILEFROMTEXTURE: { auto texturepos = scriptfile_getposition(script); @@ -1117,7 +868,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (qloadkvx(nextvoxid, fn)) + if (voxDefine(nextvoxid, fn)) { Printf("Failure loading voxel file \"%s\"\n",fn.GetChars()); break; @@ -1588,7 +1339,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (qloadkvx(nextvoxid, fn)) + if (voxDefine(nextvoxid, fn)) { voxelpos.Message(MSG_ERROR, "Failure loading voxel file \"%s\"",fn.GetChars()); break; @@ -1629,14 +1380,14 @@ static int32_t defsparser(scriptfile *script) { double scale=1.0; scriptfile_getdouble(script,&scale); - voxscale[lastvoxid] = (int32_t)(65536*scale); + voxscale[lastvoxid] = (float)scale; if (voxmodels[lastvoxid]) voxmodels[lastvoxid]->scale = scale; break; } case T_ROTATE: - voxrotate[lastvoxid>>3] |= (1 << (lastvoxid&7)); + voxrotate.Set(lastvoxid); break; } } @@ -1644,69 +1395,8 @@ static int32_t defsparser(scriptfile *script) } break; case T_SKYBOX: - { - auto skyboxpos = scriptfile_getposition(script); - FString fn[6]; - FScanner::SavedPos modelend; - int32_t i, tile = -1, pal = 0, happy = 1; - int flags = 0; - - static const tokenlist skyboxtokens[] = - { - { "tile" ,T_TILE }, - { "pal" ,T_PAL }, - { "ft" ,T_FRONT },{ "front" ,T_FRONT },{ "forward",T_FRONT }, - { "rt" ,T_RIGHT },{ "right" ,T_RIGHT }, - { "bk" ,T_BACK },{ "back" ,T_BACK }, - { "lf" ,T_LEFT },{ "left" ,T_LEFT },{ "lt" ,T_LEFT }, - { "up" ,T_TOP },{ "top" ,T_TOP },{ "ceiling",T_TOP },{ "ceil" ,T_TOP }, - { "dn" ,T_BOTTOM },{ "bottom" ,T_BOTTOM },{ "floor" ,T_BOTTOM },{ "down" ,T_BOTTOM }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - }; - - if (scriptfile_getbraces(script,&modelend)) break; - while (!scriptfile_endofblock(script, modelend)) - { - switch (getatoken(script,skyboxtokens,countof(skyboxtokens))) - { - //case T_ERROR: Printf("Error on line %s:%d in skybox tokens\n",script->filename,linenum); break; - case T_TILE: - scriptfile_getsymbol(script,&tile); break; - case T_PAL: - scriptfile_getsymbol(script,&pal); break; - case T_FRONT: - scriptfile_getstring(script,&fn[0]); break; - case T_RIGHT: - scriptfile_getstring(script,&fn[1]); break; - case T_BACK: - scriptfile_getstring(script,&fn[2]); break; - case T_LEFT: - scriptfile_getstring(script,&fn[3]); break; - case T_TOP: - scriptfile_getstring(script,&fn[4]); break; - case T_BOTTOM: - scriptfile_getstring(script,&fn[5]); break; - - } - } - - if (tile < 0) skyboxpos.Message(MSG_ERROR, "skybox: missing 'tile number'"), happy=0; - for (i=0; i<6; i++) - { - if (fn[i].IsEmpty()) skyboxpos.Message(MSG_ERROR, "skybox: missing '%s filename'", skyfaces[i]), happy = 0; - // FIXME? - if (!fileSystem.FileExists(fn[i])) - happy = 0; - } - if (!happy) break; - - const char* fns[] = { fn[0].GetChars(), fn[1].GetChars(), fn[2].GetChars(), fn[3].GetChars(), fn[4].GetChars(), fn[5].GetChars() }; - tileSetSkybox(tile, pal, fns, flags); - } - break; + parseSkybox(*script, pos); + break; case T_HIGHPALOOKUP: { int32_t basepal=-1, pal=-1; @@ -1914,191 +1604,8 @@ static int32_t defsparser(scriptfile *script) } break; case T_TEXTURE: - { - FScanner::SavedPos textureend; - int32_t tile=-1, token; - - static const tokenlist texturetokens[] = - { - { "pal", T_PAL }, - { "detail", T_DETAIL }, - { "glow", T_GLOW }, - { "specular",T_SPECULAR }, - { "normal", T_NORMAL }, - }; - - if (scriptfile_getsymbol(script,&tile)) break; - if (scriptfile_getbraces(script,&textureend)) break; - while (!scriptfile_endofblock(script, textureend)) - { - token = getatoken(script,texturetokens,countof(texturetokens)); - switch (token) - { - case T_PAL: - { - auto palpos = scriptfile_getposition(script); - FScanner::SavedPos palend; - int32_t pal=-1, xsiz = 0, ysiz = 0; - FString fn; - double alphacut = -1.0, xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; - uint8_t flags = 0; - - static const tokenlist texturetokens_pal[] = - { - { "file", T_FILE },{ "name", T_FILE }, - { "alphacut", T_ALPHACUT }, - { "detailscale", T_XSCALE }, { "scale", T_XSCALE }, { "xscale", T_XSCALE }, { "intensity", T_XSCALE }, - { "yscale", T_YSCALE }, - { "specpower", T_SPECPOWER }, { "specularpower", T_SPECPOWER }, { "parallaxscale", T_SPECPOWER }, - { "specfactor", T_SPECFACTOR }, { "specularfactor", T_SPECFACTOR }, { "parallaxbias", T_SPECFACTOR }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - { "orig_sizex", T_ORIGSIZEX }, { "orig_sizey", T_ORIGSIZEY } - }; - - if (scriptfile_getsymbol(script,&pal)) break; - if (scriptfile_getbraces(script,&palend)) break; - while (!scriptfile_endofblock(script, palend)) - { - switch (getatoken(script,texturetokens_pal,countof(texturetokens_pal))) - { - case T_FILE: - scriptfile_getstring(script,&fn); break; - case T_ALPHACUT: - scriptfile_getdouble(script,&alphacut); break; - case T_XSCALE: - scriptfile_getdouble(script,&xscale); break; - case T_YSCALE: - scriptfile_getdouble(script,&yscale); break; - case T_SPECPOWER: - scriptfile_getdouble(script,&specpower); break; - case T_SPECFACTOR: - scriptfile_getdouble(script,&specfactor); break; - case T_ORIGSIZEX: - scriptfile_getnumber(script, &xsiz); - break; - case T_ORIGSIZEY: - scriptfile_getnumber(script, &ysiz); - break; - default: - break; - } - } - - if ((unsigned)tile >= MAXUSERTILES) break; // message is printed later - if ((unsigned)pal >= MAXPALOOKUPS - RESERVEDPALS) - { - palpos.Message(MSG_ERROR, "missing or invalid 'palette number' for texture definition"); - break; - } - if (fn.IsEmpty()) - { - palpos.Message(MSG_ERROR, "missing 'file name' for texture definition"); - break; - } - - if (!fileSystem.FileExists(fn)) - { - palpos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); - break; - } - - if (xsiz > 0 && ysiz > 0) - { - tileSetDummy(tile, xsiz, ysiz); - } - xscale = 1.0f / xscale; - yscale = 1.0f / yscale; - - tileSetHightileReplacement(tile,pal,fn,alphacut,xscale,yscale, specpower, specfactor,flags); - } - break; - case T_DETAIL: case T_GLOW: case T_SPECULAR: case T_NORMAL: - { - auto detailpos = scriptfile_getposition(script); - FScanner::SavedPos detailend; - int32_t pal = 0; - char flags = 0; - FString fn; - double xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; - - static const tokenlist texturetokens_pal[] = - { - { "file", T_FILE },{ "name", T_FILE }, - { "alphacut", T_ALPHACUT }, - { "detailscale", T_XSCALE }, { "scale", T_XSCALE }, { "xscale", T_XSCALE }, { "intensity", T_XSCALE }, - { "yscale", T_YSCALE }, - { "specpower", T_SPECPOWER }, { "specularpower", T_SPECPOWER }, { "parallaxscale", T_SPECPOWER }, - { "specfactor", T_SPECFACTOR }, { "specularfactor", T_SPECFACTOR }, { "parallaxbias", T_SPECFACTOR }, - { "nocompress", T_NOCOMPRESS }, - { "nodownsize", T_NODOWNSIZE }, - { "forcefilter", T_FORCEFILTER }, - { "artquality", T_ARTQUALITY }, - }; - - if (scriptfile_getbraces(script,&detailend)) break; - while (!scriptfile_endofblock(script, detailend)) - { - switch (getatoken(script,texturetokens_pal,countof(texturetokens_pal))) - { - case T_FILE: - scriptfile_getstring(script,&fn); break; - case T_XSCALE: - scriptfile_getdouble(script,&xscale); break; - case T_YSCALE: - scriptfile_getdouble(script,&yscale); break; - case T_SPECPOWER: - scriptfile_getdouble(script,&specpower); break; - case T_SPECFACTOR: - scriptfile_getdouble(script,&specfactor); break; - default: - break; - } - } - - if ((unsigned)tile >= MAXUSERTILES) break; // message is printed later - if (fn.IsEmpty()) - { - detailpos.Message(MSG_ERROR, "missing 'file name' for texture definition"); - break; - } - - if (!fileSystem.FileExists(fn)) - break; - - switch (token) - { - case T_DETAIL: - pal = DETAILPAL; - xscale = 1.0f / xscale; - yscale = 1.0f / yscale; - break; - case T_GLOW: - pal = GLOWPAL; - break; - case T_SPECULAR: - pal = SPECULARPAL; - break; - case T_NORMAL: - pal = NORMALPAL; - break; - } - tileSetHightileReplacement(tile,pal,fn,-1.0f,xscale,yscale, specpower, specfactor,flags); - } - break; - default: - break; - } - } - if ((unsigned)tile >= MAXUSERTILES) - { - pos.Message(MSG_ERROR, "missing or invalid 'tile number' for texture definition"); - break; - } - } - break; + parseTexture(*script, pos); + break; case T_UNDEFMODEL: case T_UNDEFMODELRANGE: @@ -2290,13 +1797,6 @@ static int32_t defsparser(scriptfile *script) } break; - case T_GLOBALGAMEFLAGS: - { - int32_t dummy; - if (scriptfile_getnumber(script,&dummy)) break; - } - break; - case T_MULTIPSKY: { FScanner::SavedPos blockend; @@ -3159,7 +2659,7 @@ static int32_t defsparser(scriptfile *script) break; FStringf name("%s.%s", resName.GetChars(), resType.GetChars()); - fileSystem.CreatePathlessCopy(resName, resID, 0); + fileSystem.CreatePathlessCopy(name, resID, 0); } break; @@ -3172,34 +2672,44 @@ static int32_t defsparser(scriptfile *script) return 0; } - -int32_t loaddefinitionsfile(const char *fn, bool loadadds) +int32_t loaddefinitionsfile(const char *fn, bool loadadds, bool cumulative) { - scriptfile *script; - - script = scriptfile_fromfile(fn); - - if (script) + bool done = false; + auto parseit = [&](int lump) { - Printf(PRINT_NONOTIFY, "Loading \"%s\"\n",fn); + FScanner sc; + sc.OpenLumpNum(lump); + sc.SetNoOctals(true); + sc.SetNoFatalErrors(true); + defsparser(&sc); + done = true; + Printf(PRINT_NONOTIFY, "\n"); + }; - defsparser(script); + if (!cumulative) + { + int lump = fileSystem.FindFile(fn); + if (lump >= 0) + { + Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fn); + parseit(lump); + } + } + else + { + int lump, lastlump = 0; + while ((lump = fileSystem.FindLumpFullName(fn, &lastlump)) >= 0) + { + Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fileSystem.GetFileFullPath(lump).GetChars()); + parseit(lump); + } } if (userConfig.AddDefs && loadadds) for (auto& m : *userConfig.AddDefs) { Printf("Loading module \"%s\"\n",m.GetChars()); - defsparser_include(m, NULL, NULL); // Q: should we let the external script see our symbol table? + defsparser_include(m, nullptr, nullptr); // Q: should we let the external script see our symbol table? + Printf(PRINT_NONOTIFY, "\n"); } - - if (script) - scriptfile_close(script); - - if (!script) return -1; - - Printf(PRINT_NONOTIFY, "\n"); - return 0; } - -// vim:ts=4: diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 4649f60a9..0498dc041 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -32,6 +32,7 @@ #include "gamecontrol.h" #include "rendering/render.h" #include "gamefuncs.h" +#include "hw_voxels.h" #ifdef USE_OPENGL # include "mdsprite.h" @@ -53,18 +54,6 @@ uint8_t globalr = 255, globalg = 255, globalb = 255; int16_t pskybits_override = -1; -// This was on the cache but is permanently allocated, so put it into something static. This needs some rethinking anyway -static TArray> voxelmemory; - -int16_t tiletovox[MAXTILES]; -int voxlumps[MAXVOXELS]; -char g_haveVoxels; -//#define kloadvoxel loadvoxel - -int32_t novoxmips = 1; - -int32_t voxscale[MAXVOXELS]; - static int32_t beforedrawrooms = 1; int32_t globalflags; @@ -73,7 +62,6 @@ static int8_t tempbuf[MAXWALLS]; static int32_t no_radarang2 = 0; static int16_t radarang[1280]; -static int32_t qradarang[10240]; const char *engineerrstr = "No error"; @@ -151,7 +139,6 @@ fixed_t qglobalang; int32_t globalpal, globalfloorpal, cosglobalang, singlobalang; int32_t cosviewingrangeglobalang, sinviewingrangeglobalang; -int32_t xyaspect; int32_t viewingrangerecip; static int32_t globalxpanning, globalypanning; @@ -227,11 +214,6 @@ static int32_t engineLoadTables(void) for (i=0; i<640; i++) radarang[1279-i] = -radarang[i]; - for (i=0; i<5120; i++) - qradarang[i] = FloatToFixed(atan((5119.5 - i) / 1280.) * (-64. / BAngRadian)); - for (i=0; i<5120; i++) - qradarang[10239-i] = -qradarang[i]; - tablesloaded = 1; } @@ -671,26 +653,8 @@ int32_t enginePreInit(void) // int32_t engineInit(void) { - if (engineLoadTables()) - return 1; - - xyaspect = -1; - - voxelmemory.Reset(); - - for (int i=0; iloadPalette(); - if (!mdinited) mdinit(); return 0; } @@ -750,80 +714,6 @@ void initspritelists(void) Numsprites = 0; } - - -// -// qloadkvx -// - - - -int32_t qloadkvx(int32_t voxindex, const char *filename) -{ - if ((unsigned)voxindex >= MAXVOXELS) - return -1; - - auto fil = fileSystem.OpenFileReader(filename); - if (!fil.isOpen()) - return -1; - - int32_t lengcnt = 0; - const int32_t lengtot = fil.GetLength(); - - for (bssize_t i=0; i= lengtot-768) - break; - } - - - if (voxmodels[voxindex]) - { - voxfree(voxmodels[voxindex]); - voxmodels[voxindex] = NULL; - } - - voxlumps[voxindex] = fileSystem.FindFile(filename); - - g_haveVoxels = 1; - - return 0; -} - -void vox_undefine(int32_t const tile) -{ - int voxindex = tiletovox[tile]; - if (voxindex < 0) - return; - - if (voxmodels[voxindex]) - { - voxfree(voxmodels[voxindex]); - voxmodels[voxindex] = NULL; - } - - voxscale[voxindex] = 65536; - voxrotate[voxindex>>3] &= ~(1 << (voxindex&7)); - tiletovox[tile] = -1; - - // TODO: nextvoxid -} - -void vox_deinit() -{ - for (auto &vox : voxmodels) - { - voxfree(vox); - vox = nullptr; - } -} - // // inside // @@ -977,26 +867,6 @@ int32_t getangle(int32_t xvect, int32_t yvect) return rv; } -fixed_t gethiq16angle(int32_t xvect, int32_t yvect) -{ - fixed_t rv; - - if ((xvect | yvect) == 0) - rv = 0; - else if (xvect == 0) - rv = IntToFixed(512 + ((yvect < 0) << 10)); - else if (yvect == 0) - rv = IntToFixed(((xvect < 0) << 10)); - else if (xvect == yvect) - rv = IntToFixed(256 + ((xvect < 0) << 10)); - else if (xvect == -yvect) - rv = IntToFixed(768 + ((xvect > 0) << 10)); - else if (abs(xvect) > abs(yvect)) - rv = ((qradarang[5120 + Scale(1280, yvect, xvect)] >> 6) + IntToFixed(((xvect < 0) << 10))) & 0x7FFFFFF; - else rv = ((qradarang[5120 - Scale(1280, xvect, yvect)] >> 6) + IntToFixed(512 + ((yvect < 0) << 10))) & 0x7FFFFFF; - - return rv; -} // Gets the BUILD unit height and z offset of a sprite. // Returns the z offset, 'height' may be NULL. @@ -1865,3 +1735,10 @@ void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z) } +int tilehasmodelorvoxel(int const tilenume, int pal) +{ + UNREFERENCED_PARAMETER(pal); + return + (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || + (r_voxels && tiletovox[tilenume] != -1); +} diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index a637674f9..422e40605 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -16,6 +16,7 @@ #include "texturemanager.h" #include "hw_renderstate.h" #include "printf.h" +#include "hw_voxels.h" #include "../../glbackend/glbackend.h" static int32_t curextra=MAXTILES; @@ -23,6 +24,7 @@ static int32_t curextra=MAXTILES; #define MIN_CACHETIME_PRINT 10 using namespace Polymost; +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate); static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet) { @@ -1538,6 +1540,11 @@ int32_t polymost_mddraw(tspriteptr_t tspr) return 0; } +void voxfree(voxmodel_t* m) +{ + if (m) delete m; +} + static void mdfree(mdmodel_t *vm) { if (vm->mdnum == 1) { voxfree((voxmodel_t *)vm); return; } diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index f6f75b98c..118212656 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -26,6 +26,7 @@ Ken Silverman's official web site: http://www.advsys.net/ken #include "hw_drawinfo.h" #include "gamestruct.h" #include "gamestruct.h" +#include "hw_voxels.h" typedef struct { @@ -35,11 +36,13 @@ typedef struct { } vec3d_t; static_assert(sizeof(vec3d_t) == sizeof(double) * 3); +int32_t xyaspect = -1; int skiptile = -1; FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap = 0); +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate); int checkTranslucentReplacement(FTextureID picnum, int pal); @@ -2719,9 +2722,9 @@ void polymost_drawsprite(int32_t snum) if ((globalorientation & 48) != 48) // only non-voxel sprites should do this { - int const flag = hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize; - off = { (int32_t)tspr->xoffset + (flag ? TileFiles.tiledata[globalpicnum].h_xoffs : tileLeftOffset(globalpicnum)), - (int32_t)tspr->yoffset + (flag ? TileFiles.tiledata[globalpicnum].h_yoffs : tileTopOffset(globalpicnum)) }; + int const flag = hw_hightile && TileFiles.tiledata[globalpicnum].hiofs.xsize; + off = { (int32_t)tspr->xoffset + (flag ? TileFiles.tiledata[globalpicnum].hiofs.xoffs : tileLeftOffset(globalpicnum)), + (int32_t)tspr->yoffset + (flag ? TileFiles.tiledata[globalpicnum].hiofs.yoffs : tileTopOffset(globalpicnum)) }; } int32_t method = DAMETH_MASK | DAMETH_CLAMPED; @@ -2750,14 +2753,14 @@ void polymost_drawsprite(int32_t snum) if ((tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) { int num = tiletovox[tspr->picnum]; - if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num>>3] & (1<<(num&7)))) return; + if (polymost_voxdraw(voxmodels[num], tspr, voxrotate[num])) return; break; // else, render as flat sprite } if ((tspr->cstat & 48) == 48 && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum]) { int num = tspr->picnum; - polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num >> 3] & (1 << (num & 7))); + polymost_voxdraw(voxmodels[tspr->picnum], tspr, voxrotate[num]); return; } } @@ -2781,8 +2784,8 @@ void polymost_drawsprite(int32_t snum) vec2_t tsiz; - if (hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize) - tsiz = { TileFiles.tiledata[globalpicnum].h_xsize, TileFiles.tiledata[globalpicnum].h_ysize }; + if (hw_hightile && TileFiles.tiledata[globalpicnum].hiofs.xsize) + tsiz = { TileFiles.tiledata[globalpicnum].hiofs.xsize, TileFiles.tiledata[globalpicnum].hiofs.ysize }; else tsiz = { tileWidth(globalpicnum), tileHeight(globalpicnum) }; @@ -3312,7 +3315,7 @@ void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, f *tposx = (x << 1) + Scale(dx, i, j) - dax; *tposy = (y << 1) + Scale(dy, i, j) - day; - *tang = ((gethiq16angle(dx, dy) << 1) - daang) & 0x7FFFFFF; + *tang = ((bvectangbam(dx, dy).asq16() << 1) - daang) & 0x7FFFFFF; inpreparemirror = 1; @@ -3494,6 +3497,23 @@ static void sortsprites(int const start, int const end) } } +static bool spriteIsModelOrVoxel(const spritetype* tspr) +{ + if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD) + return false; + + if (hw_models) + { + auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)]; + if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true; + } + + auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB; + if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true; + return (slabalign && voxmodels[tspr->picnum]); +} + + // // drawmasks // @@ -3817,4 +3837,151 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect) xdimscale = Scale(320, xyaspect, xdimen); } +//Draw voxel model as perfect cubes +int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate) +{ + float f, g, k0, zoff; + + if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack + return 0; + + if ((tspr->cstat & 48) == 32) + return 0; + + if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) + { + int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16); + tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. + } + + + vec3f_t m0 = { m->scale, m->scale, m->scale }; + vec3f_t a0 = { 0, 0, m->zadd * m->scale }; + + k0 = m->bscale / 64.f; + f = (float)tspr->xrepeat * (256.f / 320.f) * k0; + if ((sprite[tspr->owner].cstat & 48) == 16) + { + f *= 1.25f; + a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20); + a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20); + } + + if (globalorientation & 8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping + if (globalorientation & 4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping + + m0.x *= f; a0.x *= f; f = -f; + m0.y *= f; a0.y *= f; + f = (float)tspr->yrepeat * k0; + m0.z *= f; a0.z *= f; + + k0 = (float)(tspr->z + spriteext[tspr->owner].position_offset.z); + f = ((globalorientation & 8) && (sprite[tspr->owner].cstat & 48) != 0) ? -4.f : 4.f; + k0 -= (tspr->yoffset * tspr->yrepeat) * f * m->bscale; + zoff = m->siz.z * .5f; + if (!(tspr->cstat & 128)) + zoff += m->piv.z; + else if ((tspr->cstat & 48) != 48) + { + zoff += m->piv.z; + zoff -= m->siz.z * .5f; + } + if (globalorientation & 8) zoff = m->siz.z - zoff; + + f = (65536.f * 512.f) / ((float)xdimen * viewingrange); + g = 32.f / ((float)xdimen * Polymost::gxyaspect); + + int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK); + + m0.y *= f; a0.y = (((float)(tspr->x + spriteext[tspr->owner].position_offset.x - globalposx)) * (1.f / 1024.f) + a0.y) * f; + m0.x *= -f; a0.x = (((float)(tspr->y + spriteext[tspr->owner].position_offset.y - globalposy)) * -(1.f / 1024.f) + a0.x) * -f; + m0.z *= g; a0.z = (((float)(k0 - globalposz - shadowHack)) * -(1.f / 16384.f) + a0.z) * g; + + float mat[16]; + md3_vox_calcmat_common(tspr, &a0, f, mat); + + //Mirrors + if (Polymost::grhalfxdown10x < 0) + { + mat[0] = -mat[0]; + mat[4] = -mat[4]; + mat[8] = -mat[8]; + mat[12] = -mat[12]; + } + + if (shadowHack) + { + GLInterface.SetDepthFunc(DF_LEqual); + } + + + int winding = ((Polymost::grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW; + GLInterface.SetCull(Cull_Back, winding); + + float pc[4]; + + pc[0] = pc[1] = pc[2] = 1.f; + + + if (!shadowHack) + { + pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f; + pc[3] *= 1.0f - spriteext[tspr->owner].alpha; + + SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); + + if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f) + GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); + } + else pc[3] = 1.f; + GLInterface.SetShade(std::max(0, globalshade), numshades); + //------------ + + //transform to Build coords + float omat[16]; + memcpy(omat, mat, sizeof(omat)); + + f = 1.f / 64.f; + g = m0.x * f; mat[0] *= g; mat[1] *= g; mat[2] *= g; + g = m0.y * f; mat[4] = omat[8] * g; mat[5] = omat[9] * g; mat[6] = omat[10] * g; + g = -m0.z * f; mat[8] = omat[4] * g; mat[9] = omat[5] * g; mat[10] = omat[6] * g; + // + mat[12] -= (m->piv.x * mat[0] + m->piv.y * mat[4] + zoff * mat[8]); + mat[13] -= (m->piv.x * mat[1] + m->piv.y * mat[5] + zoff * mat[9]); + mat[14] -= (m->piv.x * mat[2] + m->piv.y * mat[6] + zoff * mat[10]); + // + //Let OpenGL (and perhaps hardware :) handle the matrix rotation + mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f; + + for (int i = 0; i < 15; i++) mat[i] *= 1024.f; + + // Adjust to backend coordinate system being used by the vertex buffer. + for (int i = 4; i < 8; i++) + { + float f = mat[i]; + mat[i] = -mat[i + 4]; + mat[i + 4] = -f; + } + + GLInterface.SetMatrix(Matrix_Model, mat); + + int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal); + GLInterface.SetPalswap(globalpal); + GLInterface.SetFade(sector[tspr->sectnum].floorpal); + + auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture()); + GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true); + GLInterface.SetModel(m->model, 0, 0, 0); + GLInterface.Draw(DT_Triangles, 0, 0); + GLInterface.SetModel(nullptr, 0, 0, 0); + GLInterface.SetCull(Cull_None); + + if (shadowHack) + { + GLInterface.SetDepthFunc(DF_Less); + } + GLInterface.SetIdentityMatrix(Matrix_Model); + return 1; +} + diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp deleted file mode 100644 index 6a6e8d134..000000000 --- a/source/build/src/voxmodel.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//--------------------------------------- VOX LIBRARY BEGINS --------------------------------------- - -#ifdef USE_OPENGL - -#include "compat.h" -#include "build.h" -#include "engine_priv.h" -#include "polymost.h" -#include "mdsprite.h" -#include "v_video.h" -#include "flatvertices.h" -#include "hw_renderstate.h" -#include "texturemanager.h" -#include "voxels.h" -#include "gamecontrol.h" -#include "hw_models.h" -#include "printf.h" - -#include "palette.h" -#include "../../glbackend/glbackend.h" - -using namespace Polymost; - -void voxfree(voxmodel_t *m) -{ - if (m) delete m; -} - -voxmodel_t *voxload(int lumpnum) -{ - FVoxel* voxel = R_LoadKVX(lumpnum); - if (voxel != nullptr) - { - voxmodel_t* vm = new voxmodel_t; - *vm = {}; - auto pivot = voxel->Mips[0].Pivot; - vm->mdnum = 1; //VOXel model id - vm->scale = vm->bscale = 1.f; - vm->piv.x = float(pivot.X); - vm->piv.y = float(pivot.Y); - vm->piv.z = float(pivot.Z); - vm->siz.x = voxel->Mips[0].SizeX; - vm->siz.y = voxel->Mips[0].SizeY; - vm->siz.z = voxel->Mips[0].SizeZ; - vm->is8bit = true; - voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here. - vm->model = new FVoxelModel(voxel, true); - return vm; - } - return nullptr; -} - -//Draw voxel model as perfect cubes -int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate) -{ - float f, g, k0, zoff; - - if ((intptr_t)m == (intptr_t)(-1)) // hackhackhack - return 0; - - if ((tspr->cstat & 48) == 32) - return 0; - - if ((tspr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) - { - int myclock = (PlayClock << 3) + MulScale(4 << 3, pm_smoothratio, 16); - tspr->ang = (tspr->ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. - } - - - vec3f_t m0 = { m->scale, m->scale, m->scale }; - vec3f_t a0 = { 0, 0, m->zadd*m->scale }; - - k0 = m->bscale / 64.f; - f = (float) tspr->xrepeat * (256.f/320.f) * k0; - if ((sprite[tspr->owner].cstat&48)==16) - { - f *= 1.25f; - a0.y -= tspr->xoffset * bcosf(spriteext[tspr->owner].angoff, -20); - a0.x += tspr->xoffset * bsinf(spriteext[tspr->owner].angoff, -20); - } - - if (globalorientation&8) { m0.z = -m0.z; a0.z = -a0.z; } //y-flipping - if (globalorientation&4) { m0.x = -m0.x; a0.x = -a0.x; a0.y = -a0.y; } //x-flipping - - m0.x *= f; a0.x *= f; f = -f; - m0.y *= f; a0.y *= f; - f = (float) tspr->yrepeat * k0; - m0.z *= f; a0.z *= f; - - k0 = (float) (tspr->z+spriteext[tspr->owner].position_offset.z); - f = ((globalorientation&8) && (sprite[tspr->owner].cstat&48)!=0) ? -4.f : 4.f; - k0 -= (tspr->yoffset*tspr->yrepeat)*f*m->bscale; - zoff = m->siz.z*.5f; - if (!(tspr->cstat&128)) - zoff += m->piv.z; - else if ((tspr->cstat&48) != 48) - { - zoff += m->piv.z; - zoff -= m->siz.z*.5f; - } - if (globalorientation&8) zoff = m->siz.z-zoff; - - f = (65536.f*512.f) / ((float)xdimen*viewingrange); - g = 32.f / ((float)xdimen*gxyaspect); - - int const shadowHack = !!(tspr->clipdist & TSPR_FLAGS_MDHACK); - - m0.y *= f; a0.y = (((float)(tspr->x+spriteext[tspr->owner].position_offset.x-globalposx)) * (1.f/1024.f) + a0.y) * f; - m0.x *=-f; a0.x = (((float)(tspr->y+spriteext[tspr->owner].position_offset.y-globalposy)) * -(1.f/1024.f) + a0.x) * -f; - m0.z *= g; a0.z = (((float)(k0 -globalposz - shadowHack)) * -(1.f/16384.f) + a0.z) * g; - - float mat[16]; - md3_vox_calcmat_common(tspr, &a0, f, mat); - - //Mirrors - if (grhalfxdown10x < 0) - { - mat[0] = -mat[0]; - mat[4] = -mat[4]; - mat[8] = -mat[8]; - mat[12] = -mat[12]; - } - - if (shadowHack) - { - GLInterface.SetDepthFunc(DF_LEqual); - } - - - int winding = ((grhalfxdown10x >= 0) ^ ((globalorientation & 8) != 0) ^ ((globalorientation & 4) != 0)) ? Winding_CW : Winding_CCW; - GLInterface.SetCull(Cull_Back, winding); - - float pc[4]; - - pc[0] = pc[1] = pc[2] = 1.f; - - - if (!shadowHack) - { - pc[3] = (tspr->cstat & 2) ? glblend[tspr->blend].def[!!(tspr->cstat & 512)].alpha : 1.0f; - pc[3] *= 1.0f - spriteext[tspr->owner].alpha; - - SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); - - if (!(tspr->cstat & 2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f) - GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); - } - else pc[3] = 1.f; - GLInterface.SetShade(std::max(0, globalshade), numshades); - //------------ - - //transform to Build coords - float omat[16]; - memcpy(omat, mat, sizeof(omat)); - - f = 1.f/64.f; - g = m0.x*f; mat[0] *= g; mat[1] *= g; mat[2] *= g; - g = m0.y*f; mat[4] = omat[8]*g; mat[5] = omat[9]*g; mat[6] = omat[10]*g; - g =-m0.z*f; mat[8] = omat[4]*g; mat[9] = omat[5]*g; mat[10] = omat[6]*g; - // - mat[12] -= (m->piv.x*mat[0] + m->piv.y*mat[4] + zoff*mat[8]); - mat[13] -= (m->piv.x*mat[1] + m->piv.y*mat[5] + zoff*mat[9]); - mat[14] -= (m->piv.x*mat[2] + m->piv.y*mat[6] + zoff*mat[10]); - // - //Let OpenGL (and perhaps hardware :) handle the matrix rotation - mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f; - - for (int i = 0; i < 15; i++) mat[i] *= 1024.f; - - // Adjust to backend coordinate system being used by the vertex buffer. - for (int i = 4; i < 8; i++) - { - float f = mat[i]; - mat[i] = -mat[i + 4]; - mat[i + 4] = -f; - } - - GLInterface.SetMatrix(Matrix_Model, mat); - - int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal); - GLInterface.SetPalswap(globalpal); - GLInterface.SetFade(sector[tspr->sectnum].floorpal); - - auto tex = TexMan.GetGameTexture(m->model->GetPaletteTexture()); - GLInterface.SetTexture(tex, TRANSLATION(Translation_Remap + curbasepal, globalpal), CLAMP_NOFILTER_XY, true); - GLInterface.SetModel(m->model, 0, 0, 0); - GLInterface.Draw(DT_Triangles, 0, 0); - GLInterface.SetModel(nullptr, 0, 0, 0); - GLInterface.SetCull(Cull_None); - - if (shadowHack) - { - GLInterface.SetDepthFunc(DF_Less); - } - GLInterface.SetIdentityMatrix(Matrix_Model); - return 1; -} - -extern int voxlumps[MAXVOXELS]; -void (*PolymostProcessVoxels_Callback)(void) = NULL; -void PolymostProcessVoxels(void) -{ - if (PolymostProcessVoxels_Callback) - PolymostProcessVoxels_Callback(); - - if (g_haveVoxels != 1) - return; - - g_haveVoxels = 2; - - Printf(PRINT_NONOTIFY, "Generating voxel models for Polymost. This may take a while...\n"); - - for (int i = 0; i < MAXVOXELS; i++) - { - int lumpnum = voxlumps[i]; - if (lumpnum > 0) - { - voxmodels[i] = voxload(lumpnum); - if (voxmodels[i]) - voxmodels[i]->scale = voxscale[i] * (1.f / 65536.f); - else - Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum)); - } - } -} - -#endif - -//---------------------------------------- VOX LIBRARY ENDS ---------------------------------------- diff --git a/source/common/audio/music/music_config.cpp b/source/common/audio/music/music_config.cpp index 12573b781..86eef267e 100644 --- a/source/common/audio/music/music_config.cpp +++ b/source/common/audio/music/music_config.cpp @@ -85,17 +85,17 @@ CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA FORWARD_BOOL_CVAR(adl_fullpan); } -CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_CVAR(adl_bank); } -CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(adl_use_custom_bank); } -CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(adl_custom_bank); } @@ -261,12 +261,12 @@ CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUA FORWARD_BOOL_CVAR(opn_fullpan); } -CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(opn_use_custom_bank); } -CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(opn_custom_bank); } diff --git a/source/common/console/c_bind.cpp b/source/common/console/c_bind.cpp index 1e5893875..c70f414f9 100644 --- a/source/common/console/c_bind.cpp +++ b/source/common/console/c_bind.cpp @@ -707,6 +707,12 @@ void ReadBindings(int lump, bool override) dest = &AutomapBindings; sc.MustGetString(); } + else if (sc.Compare("unbind")) + { + sc.MustGetString(); + dest->UnbindKey(sc.String); + continue; + } key = GetConfigKeyFromName(sc.String); sc.MustGetString(); dest->SetBind(key, sc.String, override); diff --git a/source/common/engine/sc_man.cpp b/source/common/engine/sc_man.cpp index fa9a2f6c4..f24f25d92 100644 --- a/source/common/engine/sc_man.cpp +++ b/source/common/engine/sc_man.cpp @@ -1287,6 +1287,42 @@ void FScanner::AddSymbol(const char* name, double value) symbols.Insert(name, sym); } +//========================================================================== +// +// +// +//========================================================================== + +int FScanner::StartBraces(FScanner::SavedPos* braceend) +{ + if (CheckString("{")) + { + auto here = SavePos(); + SkipToEndOfBlock(); + *braceend = SavePos(); + RestorePos(here); + return 0; + } + else + { + ScriptError("'{' expected"); + return -1; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FScanner::FoundEndBrace(FScanner::SavedPos& braceend) +{ + auto here = SavePos(); + return here.SavedScriptPtr >= braceend.SavedScriptPtr; +} + + //========================================================================== // // a class that remembers a parser position diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index 6c37806a8..64690d24b 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -94,6 +94,8 @@ public: inline void AddSymbol(const char* name, uint32_t value) { return AddSymbol(name, uint64_t(value)); } void AddSymbol(const char* name, double value); void SkipToEndOfBlock(); + int StartBraces(FScanner::SavedPos* braceend); + bool FoundEndBrace(FScanner::SavedPos& braceend); static FString TokenName(int token, const char *string=NULL); @@ -113,7 +115,30 @@ public: void MustGetNumber(bool evaluate = false); bool CheckNumber(bool evaluate = false); + bool GetNumber(int& var, bool evaluate = false) + { + if (!GetNumber(evaluate)) return false; + var = Number; + return true; + } + + bool GetString(FString& var) + { + if (!GetString()) return false; + var = String; + return true; + } + bool GetFloat(bool evaluate = false); + + bool GetFloat(double& var, bool evaluate = false) + { + if (!GetFloat(evaluate)) return false; + var = Float; + return true; + } + + void MustGetFloat(bool evaluate = false); bool CheckFloat(bool evaluate = false); diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index 00de98cdc..2adca1160 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -233,12 +233,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) } name.ToLower(); + if (name.IndexOf("__macosx") == 0) + continue; // skip Apple garbage. At this stage only the root folder matters, if (i == 0) { // check for special names, if one of these gets found this must be treated as a normal zip. bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); if (isspecial) break; - name0 = name; + name0 = name.Left(name.LastIndexOf("/")+1); } else { @@ -252,7 +254,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) // at least one of the more common definition lumps must be present. for (auto &p : filter->requiredPrefixes) { - if (name.IndexOf(name0 + p) == 0) + if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == name.Len() - strlen(p)) { foundspeciallump = true; break; @@ -272,7 +274,6 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) int len = LittleShort(zip_fh->NameLength); FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); - if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + @@ -284,7 +285,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); return false; } - + + if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0) + { + skipped++; + continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. + } + if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); + // skip Directories if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) { diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 0ea4ac7a6..dae98edf5 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -76,14 +76,14 @@ struct FileSystem::LumpRecord shortName.String[8] = 0; longName = ""; Namespace = lump->GetNamespace(); - resourceId = 0; + resourceId = -1; } else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName()) { shortName.qword = 0; longName = ""; Namespace = ns_hidden; - resourceId = 0; + resourceId = -1; } else { diff --git a/source/common/platform/posix/sdl/i_system.cpp b/source/common/platform/posix/sdl/i_system.cpp index 1dc656a69..b2f0d8436 100644 --- a/source/common/platform/posix/sdl/i_system.cpp +++ b/source/common/platform/posix/sdl/i_system.cpp @@ -175,10 +175,11 @@ void I_PrintStr(const char *cp) { const char * srcp = cp; FString printData = ""; + bool terminal = isatty(STDOUT_FILENO); while (*srcp != 0) { - if (*srcp == 0x1c && con_printansi) + if (*srcp == 0x1c && con_printansi && terminal) { srcp += 1; EColorRange range = V_ParseFontColor((const uint8_t*&)srcp, CR_UNTRANSLATED, CR_YELLOW); @@ -224,7 +225,7 @@ void I_PrintStr(const char *cp) if (StartScreen) CleanProgressBar(); fputs(printData.GetChars(),stdout); - fputs("\033[0m",stdout); + if (terminal) fputs("\033[0m",stdout); if (StartScreen) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos); } diff --git a/source/common/rendering/hwrenderer/data/flatvertices.cpp b/source/common/rendering/hwrenderer/data/flatvertices.cpp index 47ae19ec3..5bc37bcb7 100644 --- a/source/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/source/common/rendering/hwrenderer/data/flatvertices.cpp @@ -80,6 +80,8 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) mVertexBuffer = screen->CreateVertexBuffer(); mIndexBuffer = screen->CreateIndexBuffer(); + int data[4] = {}; + mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes. unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex); mVertexBuffer->SetData(bytesize, nullptr, false); diff --git a/source/common/rendering/hwrenderer/data/hw_renderstate.h b/source/common/rendering/hwrenderer/data/hw_renderstate.h index 5f373adfc..54aab25f8 100644 --- a/source/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/source/common/rendering/hwrenderer/data/hw_renderstate.h @@ -200,9 +200,8 @@ struct StreamData FVector4 uSplitBottomPlane; FVector4 uDetailParms; -#ifdef NPOT_EMULATION - FVector2 uNpotEmulation; -#endif + FVector4 uNpotEmulation; + FVector4 padding1, padding2, padding3; }; class FRenderState @@ -274,7 +273,7 @@ public: mSpecialEffect = EFF_NONE; mLightIndex = -1; mStreamData.uInterpolationFactor = 0; - mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; + mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mBias.Reset(); mPassType = NORMAL_PASS; @@ -295,7 +294,7 @@ public: mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 1.0f }; mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { 0,0 }; + mStreamData.uNpotEmulation = { 0,0,0,0 }; #endif mModelMatrix.loadIdentity(); mTextureMatrix.loadIdentity(); @@ -490,7 +489,7 @@ public: void SetNpotEmulation(float factor, float offset) { #ifdef NPOT_EMULATION - mStreamData.uNpotEmulation = { offset, factor }; + mStreamData.uNpotEmulation = { offset, factor, 0, 0 }; #endif } diff --git a/source/common/rendering/hwrenderer/data/hw_skydome.cpp b/source/common/rendering/hwrenderer/data/hw_skydome.cpp index 2a16ccbf3..5d5ee8000 100644 --- a/source/common/rendering/hwrenderer/data/hw_skydome.cpp +++ b/source/common/rendering/hwrenderer/data/hw_skydome.cpp @@ -202,7 +202,7 @@ void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip) // And the texture coordinates. if (zflip) r = mRows * 2 - r; - vert.u = 0.5 + (-c / (float)mColumns); + vert.u = 0.5f + (-c / (float)mColumns); vert.v = (r / (float)(2*mRows)); // And finally the vertex. @@ -413,11 +413,13 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_ { modelMatrix.translate(0.f, -1250.f, 0.f); modelMatrix.scale(1.f, texh / 230.f, 1.f); + yscale = 1.f; } else if (texh <= 240) { modelMatrix.translate(0.f, (200 - texh + texskyoffset) * skyoffsetfactor, 0.f); modelMatrix.scale(1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f, 1.f); + yscale = 1.f; } else { diff --git a/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp b/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp index 7ce16369b..a71523a46 100644 --- a/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/source/common/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -152,6 +152,10 @@ void PolyFrameBuffer::FlushDrawCommands() } } +EXTERN_CVAR(Float, vid_brightness) +EXTERN_CVAR(Float, vid_contrast) +EXTERN_CVAR(Float, vid_saturation) + void PolyFrameBuffer::Update() { twoD.Reset(); @@ -177,8 +181,9 @@ void PolyFrameBuffer::Update() if (dst) { #if 1 + // [GEC] with the help of dpJudas a new system of copying and applying gamma in the video buffer auto copyqueue = std::make_shared(&mFrameMemory); - copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, pixelsize); + copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, vid_gamma, vid_contrast, vid_brightness, vid_saturation); DrawerThreads::Execute(copyqueue); #else for (int y = 0; y < h; y++) @@ -366,6 +371,40 @@ FTexture *PolyFrameBuffer::WipeEndScreen() TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) { + // [GEC] Really necessary to apply gamma, brightness, contrast and saturation for screenshot + + std::vector gammatablebuf(256); + uint8_t* gammatable = gammatablebuf.data(); + + float InvGamma = 1.0f / clamp(vid_gamma, 0.1f, 4.f); + float Brightness = clamp(vid_brightness, -0.8f, 0.8f); + float Contrast = clamp(vid_contrast, 0.1f, 3.f); + float Saturation = clamp(vid_saturation, -15.0f, 15.f); + + for (int x = 0; x < 256; x++) + { + float ramp = (float)(x / 255.f); + // Apply Contrast + // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); + if(vid_contrast != 1.0f) + ramp = (((ramp - 0.5f) * Contrast) + 0.5f); + + // Apply Brightness + // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); + if (vid_brightness != 0.0f) + ramp += (Brightness / 2.0f); + + // Apply Gamma + // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); + if (vid_gamma != 1.0f) + ramp = pow(ramp, InvGamma); + + // Clamp ramp + ramp = clamp(ramp, 0.0f, 1.f); + + gammatable[x] = (uint8_t)(ramp * 255); + } + int w = SCREENWIDTH; int h = SCREENHEIGHT; @@ -380,9 +419,44 @@ TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_ for (int x = 0; x < w; x++) { - ScreenshotBuffer[dindex ] = pixels[sindex + 2]; - ScreenshotBuffer[dindex + 1] = pixels[sindex + 1]; - ScreenshotBuffer[dindex + 2] = pixels[sindex ]; + uint32_t red = pixels[sindex + 2]; + uint32_t green = pixels[sindex + 1]; + uint32_t blue = pixels[sindex]; + + if (vid_saturation != 1.0f) + { + float NewR = (float)(red / 255.f); + float NewG = (float)(green / 255.f); + float NewB = (float)(blue / 255.f); + + // Apply Saturation + // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); + // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); + //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 + float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 + NewR = luma + (Saturation * (NewR - luma)); + NewG = luma + (Saturation * (NewG - luma)); + NewB = luma + (Saturation * (NewB - luma)); + + // Clamp All + NewR = clamp(NewR, 0.0f, 1.f); + NewG = clamp(NewG, 0.0f, 1.f); + NewB = clamp(NewB, 0.0f, 1.f); + + red = (uint32_t)(NewR * 255.f); + green = (uint32_t)(NewG * 255.f); + blue = (uint32_t)(NewB * 255.f); + } + + // Apply Contrast / Brightness / Gamma + red = gammatable[red]; + green = gammatable[green]; + blue = gammatable[blue]; + + ScreenshotBuffer[dindex ] = red; + ScreenshotBuffer[dindex + 1] = green; + ScreenshotBuffer[dindex + 2] = blue; + dindex += 3; sindex += 4; } diff --git a/source/common/rendering/polyrenderer/backend/poly_framebuffer.h b/source/common/rendering/polyrenderer/backend/poly_framebuffer.h index a3c4eee29..76eae0ced 100644 --- a/source/common/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/source/common/rendering/polyrenderer/backend/poly_framebuffer.h @@ -96,3 +96,119 @@ private: }; inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast(screen); } + +// [GEC] Original code of dpJudas, I add the formulas of gamma, brightness, contrast and saturation. +class CopyAndApplyGammaCommand : public DrawerCommand +{ +public: + CopyAndApplyGammaCommand(void* dest, int destpitch, const void* src, int width, int height, int srcpitch, + float gamma, float contrast, float brightness, float saturation) : dest(dest), src(src), destpitch(destpitch), width(width), height(height), srcpitch(srcpitch), + gamma(gamma), contrast(contrast), brightness(brightness), saturation(saturation) + { + } + + void Execute(DrawerThread* thread) + { + float Saturation = clamp(saturation, -15.0f, 15.f); + + std::vector gammatablebuf(256); + uint8_t* gammatable = gammatablebuf.data(); + InitGammaTable(gammatable); + + int w = width; + int start = thread->skipped_by_thread(0); + int count = thread->count_for_thread(0, height); + int sstep = thread->num_cores * srcpitch; + int dstep = thread->num_cores * destpitch; + uint32_t* d = (uint32_t*)dest + start * destpitch; + const uint32_t* s = (const uint32_t*)src + start * srcpitch; + for (int y = 0; y < count; y++) + { + for (int x = 0; x < w; x++) + { + uint32_t red = RPART(s[x]); + uint32_t green = GPART(s[x]); + uint32_t blue = BPART(s[x]); + uint32_t alpha = APART(s[x]); + + if (saturation != 1.0f) + { + float NewR = (float)(red / 255.f); + float NewG = (float)(green / 255.f); + float NewB = (float)(blue / 255.f); + + // Apply Saturation + // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); + // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); + //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 + float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 + NewR = luma + (Saturation * (NewR - luma)); + NewG = luma + (Saturation * (NewG - luma)); + NewB = luma + (Saturation * (NewB - luma)); + + // Clamp All + NewR = clamp(NewR, 0.0f, 1.f); + NewG = clamp(NewG, 0.0f, 1.f); + NewB = clamp(NewB, 0.0f, 1.f); + + red = (uint32_t)(NewR * 255.f); + green = (uint32_t)(NewG * 255.f); + blue = (uint32_t)(NewB * 255.f); + } + + // Apply Contrast / Brightness / Gamma + red = gammatable[red]; + green = gammatable[green]; + blue = gammatable[blue]; + + d[x] = MAKEARGB(alpha, (uint8_t)red, (uint8_t)green, (uint8_t)blue); + } + d += dstep; + s += sstep; + } + } + +private: + void InitGammaTable(uint8_t *gammatable) + { + float InvGamma = 1.0f / clamp(gamma, 0.1f, 4.f); + float Brightness = clamp(brightness, -0.8f, 0.8f); + float Contrast = clamp(contrast, 0.1f, 3.f); + + for (int x = 0; x < 256; x++) + { + float ramp = (float)(x / 255.f); + + // Apply Contrast + // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); + if (contrast != 1.0f) + ramp = (((ramp - 0.5f) * Contrast) + 0.5f); + + // Apply Brightness + // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); + if (brightness != 0.0f) + ramp += (Brightness / 2.0f); + + // Apply Gamma + // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); + if (gamma != 1.0f) + ramp = pow(ramp, InvGamma); + + // Clamp ramp + ramp = clamp(ramp, 0.0f, 1.f); + + gammatable[x] = (uint8_t)(ramp * 255); + } + } + + void* dest; + const void* src; + int destpitch; + int width; + int height; + int srcpitch; + float gamma; + float contrast; + float brightness; + float saturation; +}; diff --git a/source/common/rendering/polyrenderer/drawers/screen_shader.cpp b/source/common/rendering/polyrenderer/drawers/screen_shader.cpp index 285c97670..7e225bef1 100644 --- a/source/common/rendering/polyrenderer/drawers/screen_shader.cpp +++ b/source/common/rendering/polyrenderer/drawers/screen_shader.cpp @@ -538,12 +538,13 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) // frag = frag * vColor; // frag.rgb = frag.rgb + uFogColor.rgb; - uint32_t startR = (int)((thread->mainVertexShader.Data.uObjectColor.r) * 255.0f); - uint32_t startG = (int)((thread->mainVertexShader.Data.uObjectColor.g) * 255.0f); - uint32_t startB = (int)((thread->mainVertexShader.Data.uObjectColor.b) * 255.0f); - uint32_t rangeR = (int)((thread->mainVertexShader.Data.uAddColor.r) * 255.0f) - startR; - uint32_t rangeG = (int)((thread->mainVertexShader.Data.uAddColor.g) * 255.0f) - startG; - uint32_t rangeB = (int)((thread->mainVertexShader.Data.uAddColor.b) * 255.0f) - startB; + // [GEC] I leave the default floating values. + float startR = thread->mainVertexShader.Data.uObjectColor.r; + float startG = thread->mainVertexShader.Data.uObjectColor.g; + float startB = thread->mainVertexShader.Data.uObjectColor.b; + float rangeR = thread->mainVertexShader.Data.uAddColor.r - startR; + float rangeG = thread->mainVertexShader.Data.uAddColor.g - startG; + float rangeB = thread->mainVertexShader.Data.uAddColor.b - startB; for (int x = x0; x < x1; x++) { @@ -555,15 +556,22 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) uint32_t gray = (r * 77 + g * 143 + b * 37) >> 8; gray += (gray >> 7); // gray*=256/255 - r = (startR + ((gray * rangeR) >> 8)) << 1; - g = (startG + ((gray * rangeG) >> 8)) << 1; - b = (startB + ((gray * rangeB) >> 8)) << 1; + // [GEC] I use the same method as in shaders using floating values. + // This avoids errors in the invulneravility colormap in Doom and Heretic. + float fgray = (float)(gray / 255.f); + float fr = (startR + (fgray * rangeR)) * 2; + float fg = (startG + (fgray * rangeG)) * 2; + float fb = (startB + (fgray * rangeB)) * 2; - r = MIN(r, (uint32_t)255); - g = MIN(g, (uint32_t)255); - b = MIN(b, (uint32_t)255); + fr = clamp(fr, 0.0f, 1.0f); + fg = clamp(fg, 0.0f, 1.0f); + fb = clamp(fb, 0.0f, 1.0f); - fragcolor[x] = MAKEARGB(a, r, g, b); + r = (uint32_t)(fr * 255.f); + g = (uint32_t)(fg * 255.f); + b = (uint32_t)(fb * 255.f); + + fragcolor[x] = MAKEARGB(a, (uint8_t)r, (uint8_t)g, (uint8_t)b); } } else diff --git a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp index e3217076d..34e44096d 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -212,13 +212,18 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag ImageBuilder builder; builder.setSize(width, height); builder.setSamples(samples); - builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32); + builder.setFormat(SceneNormalFormat); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) + { + SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; + builder.setFormat(SceneNormalFormat); + } SceneNormal.Image = builder.create(fb->device); SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneNormal.Image.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32); + viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat); SceneNormal.View = viewbuilder.create(fb->device); SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView"); } diff --git a/source/common/rendering/vulkan/renderer/vk_renderbuffers.h b/source/common/rendering/vulkan/renderer/vk_renderbuffers.h index b1df96b02..92ad9c5be 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/source/common/rendering/vulkan/renderer/vk_renderbuffers.h @@ -24,6 +24,7 @@ public: VkTextureImage SceneFog; VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; + VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32; static const int NumPipelineImages = 2; VkTextureImage PipelineImage[NumPipelineImages]; diff --git a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp index 2e0973c08..44c325ecf 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp @@ -281,7 +281,7 @@ std::unique_ptr VkRenderPassSetup::CreateRenderPass(int clearT { auto buffers = GetVulkanFrameBuffer()->GetBuffers(); - VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }; + VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat }; RenderPassBuilder builder; @@ -420,7 +420,8 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli builder.setTopology(vktopology[key.DrawType]); builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest); builder.setDepthFunc(depthfunc2vk[key.DepthFunc]); - builder.setDepthClampEnable(key.DepthClamp); + if (fb->device->UsedDeviceFeatures.depthClamp) + builder.setDepthClampEnable(key.DepthClamp); builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f); // Note: CCW and CW is intentionally swapped here because the vulkan and opengl coordinate systems differ. diff --git a/source/common/rendering/vulkan/shaders/vk_shader.cpp b/source/common/rendering/vulkan/shaders/vk_shader.cpp index 0456061fb..84f7d3d5e 100644 --- a/source/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/source/common/rendering/vulkan/shaders/vk_shader.cpp @@ -163,9 +163,8 @@ static const char *shaderBindings = R"( vec4 uSplitBottomPlane; vec4 uDetailParms; - #ifdef NPOT_EMULATION - vec2 uNpotEmulation; - #endif + vec4 uNpotEmulation; + vec4 padding1, padding2, padding3; }; layout(set = 0, binding = 3, std140) uniform StreamUBO { @@ -297,6 +296,9 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername code << defines; code << "\n$placeholder$"; // here the code can later add more needed #defines. code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; +#ifdef NPOT_EMULATION + code << "#define NPOT_EMULATION\n"; +#endif code << shaderBindings; FString placeholder = "\n"; diff --git a/source/common/rendering/vulkan/system/vk_builders.h b/source/common/rendering/vulkan/system/vk_builders.h index 5f0e3c0fc..343313bbd 100644 --- a/source/common/rendering/vulkan/system/vk_builders.h +++ b/source/common/rendering/vulkan/system/vk_builders.h @@ -45,7 +45,7 @@ public: void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); void setLinearTiling(); - bool isFormatSupported(VulkanDevice *device); + bool isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0); std::unique_ptr create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); std::unique_ptr tryCreate(VulkanDevice *device); @@ -410,7 +410,7 @@ inline void ImageBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkM allocInfo.memoryTypeBits = memoryTypeBits; } -inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) +inline bool ImageBuilder::isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures) { VkImageFormatProperties properties = { }; VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); @@ -421,6 +421,13 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) if (imageInfo.mipLevels > properties.maxMipLevels) return false; if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; + if (bufferFeatures != 0) + { + VkFormatProperties formatProperties = { }; + vkGetPhysicalDeviceFormatProperties(device->PhysicalDevice.Device, imageInfo.format, &formatProperties); + if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures) + return false; + } return true; } diff --git a/source/common/rendering/vulkan/system/vk_device.cpp b/source/common/rendering/vulkan/system/vk_device.cpp index 8fc6e8949..2e7ca9aad 100644 --- a/source/common/rendering/vulkan/system/vk_device.cpp +++ b/source/common/rendering/vulkan/system/vk_device.cpp @@ -108,8 +108,7 @@ bool VulkanDevice::CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f) { return f.samplerAnisotropy == VK_TRUE && - f.fragmentStoresAndAtomics == VK_TRUE && - f.depthClamp == VK_TRUE; + f.fragmentStoresAndAtomics == VK_TRUE; } void VulkanDevice::SelectPhysicalDevice() diff --git a/source/common/rendering/vulkan/system/vk_framebuffer.cpp b/source/common/rendering/vulkan/system/vk_framebuffer.cpp index 32d36447f..9b83b6e26 100644 --- a/source/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/source/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -390,7 +390,7 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels) { - return new VkHardwareTexture(); + return new VkHardwareTexture(numchannels); } FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) diff --git a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp index 25bd66d71..6178549ab 100644 --- a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -37,8 +37,9 @@ VkHardwareTexture *VkHardwareTexture::First = nullptr; -VkHardwareTexture::VkHardwareTexture() +VkHardwareTexture::VkHardwareTexture(int numchannels) { + mTexelsize = numchannels; Next = First; First = this; if (Next) Next->Prev = this; @@ -126,7 +127,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) if (!tex->isHardwareCanvas()) { FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); - CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer); + bool indexed = flags & CTF_Indexed; + CreateTexture(texbuffer.mWidth, texbuffer.mHeight,indexed? 1 : 4, indexed? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer, !indexed); } else { @@ -156,7 +158,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } } -void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels) +void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap) { if (w <= 0 || h <= 0) throw CVulkanError("Trying to create zero size texture"); @@ -177,7 +179,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form ImageBuilder imgbuilder; imgbuilder.setFormat(format); - imgbuilder.setSize(w, h, GetMipLevels(w, h)); + imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h)); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); mImage.Image = imgbuilder.create(fb->device); mImage.Image->SetDebugName("VkHardwareTexture.mImage"); @@ -203,7 +205,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer)); - mImage.GenerateMipmaps(cmdbuffer); + if (mipmap) mImage.GenerateMipmaps(cmdbuffer); } int VkHardwareTexture::GetMipLevels(int w, int h) @@ -268,6 +270,7 @@ uint8_t *VkHardwareTexture::MapBuffer() unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) { + CreateTexture(w, h, mTexelsize, mTexelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM, buffer, mipmap); return 0; } @@ -371,10 +374,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) int clampmode = state.mClampMode; int translation = state.mTranslation; - auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation); - if (remap) - translation = remap->Index; - clampmode = base->GetClampMode(clampmode); for (auto& set : mDescriptorSets) @@ -395,10 +394,23 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) MaterialLayerInfo *layer; auto systex = static_cast(GetLayer(0, state.mTranslation, &layer)); update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); - for (int i = 1; i < numLayers; i++) + + if (!(layer->scaleFlags & CTF_Indexed)) { - auto systex = static_cast(GetLayer(i, 0, &layer)); - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(GetLayer(i, 0, &layer)); + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + } + } + else + { + for (int i = 1; i < 3; i++) + { + auto systex = static_cast(GetLayer(i, translation, &layer)); + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + } + numLayers = 3; } auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); diff --git a/source/common/rendering/vulkan/textures/vk_hwtexture.h b/source/common/rendering/vulkan/textures/vk_hwtexture.h index 872f58aef..22958c494 100644 --- a/source/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/source/common/rendering/vulkan/textures/vk_hwtexture.h @@ -24,7 +24,7 @@ class VkHardwareTexture : public IHardwareTexture { friend class VkMaterial; public: - VkHardwareTexture(); + VkHardwareTexture(int numchannels); ~VkHardwareTexture(); static void ResetAll(); @@ -45,7 +45,7 @@ public: private: void CreateImage(FTexture *tex, int translation, int flags); - void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); + void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap); static int GetMipLevels(int w, int h); static VkHardwareTexture *First; diff --git a/source/common/statusbar/base_sbar.cpp b/source/common/statusbar/base_sbar.cpp index b0e917872..ae1a375c3 100644 --- a/source/common/statusbar/base_sbar.cpp +++ b/source/common/statusbar/base_sbar.cpp @@ -605,13 +605,13 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag // //============================================================================ -void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) +void DStatusBarCore::DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) { if (!texture.isValid()) return; FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE)); - DrawRotated(tex, x, y, angle, flags, Alpha, scaleX, scaleY, color, translation, style); + DrawRotated(tex, x, y, flags, angle, Alpha, scaleX, scaleY, color, translation, style); } void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color, int translation, ERenderStyle style) diff --git a/source/common/statusbar/base_sbar.h b/source/common/statusbar/base_sbar.h index 02c66ba26..7f892b4e4 100644 --- a/source/common/statusbar/base_sbar.h +++ b/source/common/statusbar/base_sbar.h @@ -186,7 +186,7 @@ public: void StatusbarToRealCoords(double& x, double& y, double& w, double& h) const; void DrawGraphic(FGameTexture* texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0); void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent, double clipwidth = -1.0); - void DrawRotated(FTextureID texture, double x, double y, double angle, int flags, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); + void DrawRotated(FTextureID texture, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); void DrawRotated(FGameTexture* tex, double x, double y, int flags, double angle, double Alpha, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, ERenderStyle style = STYLE_Translucent); void DrawString(FFont* font, const FString& cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY, int pt); void TransformRect(double& x, double& y, double& w, double& h, int flags = 0); diff --git a/source/common/textures/animtexture.cpp b/source/common/textures/animtexture.cpp index 6a96365a8..8f8add3f7 100644 --- a/source/common/textures/animtexture.cpp +++ b/source/common/textures/animtexture.cpp @@ -48,7 +48,6 @@ void AnimTexture::SetFrameSize(int format, int width, int height) FTexture::SetSize(width, height); Image.Resize(width * height * (format == Paletted ? 1 : 3)); memset(Image.Data(), 0, Image.Size()); - CleanHardwareTextures(); } void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) @@ -81,7 +80,6 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) } else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); } - CleanHardwareTextures(); } //=========================================================================== @@ -156,10 +154,13 @@ void AnimTextures::SetSize(int format, int width, int height) static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); tex[0]->SetSize(width, height); tex[1]->SetSize(width, height); + tex[0]->CleanHardwareData(); + tex[1]->CleanHardwareData(); } void AnimTextures::SetFrame(const uint8_t* palette, const void* data) { active ^= 1; static_cast(tex[active]->GetTexture())->SetFrame(palette, data); + tex[active]->CleanHardwareData(); } diff --git a/source/common/textures/hw_material.cpp b/source/common/textures/hw_material.cpp index f8d379cd4..a157cbc07 100644 --- a/source/common/textures/hw_material.cpp +++ b/source/common/textures/hw_material.cpp @@ -30,6 +30,7 @@ #include "v_video.h" static IHardwareTexture* (*layercallback)(int layer, int translation); +TArray usershaders; void FMaterial::SetLayerCallback(IHardwareTexture* (*cb)(int layer, int translation)) { diff --git a/source/core/automap.cpp b/source/core/automap.cpp index 902ab46a3..258ad9089 100644 --- a/source/core/automap.cpp +++ b/source/core/automap.cpp @@ -27,7 +27,6 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) //------------------------------------------------------------------------- #include "automap.h" -#include "cstat.h" #include "c_dispatch.h" #include "c_cvars.h" #include "gstrings.h" diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index 6d827a2d8..a0690d734 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -366,24 +366,14 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, binangle &obj, //--------------------------------------------------------------------------- // -// Constants and functions for use with fixedhoriz and friendly functions. +// Functions for use with fixedhoriz and friendly functions. // //--------------------------------------------------------------------------- -// 280039127 is the maximum horizon in Q16.16 the engine will handle before wrapping around. -constexpr double horizDiff = 280039127 * 3. / 100.; - -// Degrees needed to convert horizAngle into pitch degrees. -constexpr double horizDegrees = 183.503609961216825; - -// Ratio to convert inverse tangent to -90/90 degrees of pitch. -constexpr double horizRatio = horizDegrees / pi::pi(); - -// Horizon conversion functions. -inline double HorizToPitch(double horiz) { return atan2(horiz, horizDiff / 65536.) * horizRatio; } -inline double HorizToPitch(fixed_t q16horiz) { return atan2(q16horiz, horizDiff) * horizRatio; } -inline fixed_t PitchToHoriz(double horizAngle) { return xs_CRoundToInt(horizDiff * tan(horizAngle * (pi::pi() / horizDegrees))); } -inline int32_t PitchToBAM(double horizAngle) { return xs_CRoundToInt(clamp(horizAngle * (1073741823.5 / 45.), -INT32_MAX, INT32_MAX)); } +inline double HorizToPitch(double horiz) { return atan2(horiz, 128) * (180. / pi::pi()); } +inline double HorizToPitch(fixed_t q16horiz) { return atan2(q16horiz, IntToFixed(128)) * (180. / pi::pi()); } +inline fixed_t PitchToHoriz(double pitch) { return xs_CRoundToInt(IntToFixed(128) * tan(pitch * (pi::pi() / 180.))); } +inline int32_t PitchToBAM(double pitch) { return xs_CRoundToInt(clamp(pitch * (1073741823.5 / 45.), -INT32_MAX, INT32_MAX)); } inline constexpr double BAMToPitch(int32_t bam) { return bam * (45. / 1073741823.5); } @@ -512,54 +502,11 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, fixedhoriz &obj //--------------------------------------------------------------------------- // -// Double-precision implementation of `getangle()` with associated wrappers and helper functions. +// High precision vector angle function, mainly for the renderer. // //--------------------------------------------------------------------------- -inline double bradarangf(double vect) -{ - return atan(vect) * BRadAngScale; -} -inline double bvectangf(int32_t x, int32_t y) -{ - if ((x | y) == 0) - { - return 0; - } - else if (x == 0) - { - return 512 + ((y < 0) << 10); - } - else if (y == 0) - { - return ((x < 0) << 10); - } - else if (x == y) - { - return 256 + ((x < 0) << 10); - } - else if (x == -y) - { - return 768 + ((x > 0) << 10); - } - else if (abs(x) > abs(y)) - { - return fmod(bradarangf(double(y) / x) + ((x < 0) << 10), 2048.); - } - else - { - return fmod(bradarangf(double(x) / -y) + 512 + ((y < 0) << 10), 2048.); - } -} -inline int32_t bvectang(int32_t x, int32_t y) -{ - return xs_CRoundToInt(bvectangf(x, y)); -} -inline fixed_t bvectangq16(int32_t x, int32_t y) -{ - return FloatToFixed(bvectangf(x, y)); -} inline binangle bvectangbam(int32_t x, int32_t y) { - return bamang(xs_CRoundToUInt(bvectangf(x, y) * BAMUNIT)); + return radang(atan2(y, x)); } diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index e256e3d76..fb9cb3ae9 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -74,6 +74,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_draw.h" #include "gi.h" #include "gamefuncs.h" +#include "hw_voxels.h" +#include "hw_palmanager.h" CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -135,6 +137,7 @@ void SetConsoleNotifyBuffer(); bool PreBindTexture(FRenderState* state, FGameTexture*& tex, EUpscaleFlags& flags, int& scaleflags, int& clampmode, int& translation, int& overrideshader); void PostLoadSetup(); void FontCharCreated(FGameTexture* base, FGameTexture* untranslated, FGameTexture* translated); +void LoadVoxelModels(); DBaseStatusBar* StatusBar; @@ -358,7 +361,7 @@ void UserConfig::ProcessOptions() static const char* defs[] = { "-def", "-h", nullptr }; Args->CollectFiles("-def", defs, ".def"); - DefaultDef = Args->CheckValue("-def"); + UserDef = Args->CheckValue("-def"); if (DefaultCon.IsEmpty()) { @@ -582,10 +585,10 @@ int GameMain() G_SaveConfig(); C_DeinitConsole(); V_ClearFonts(); - vox_deinit(); + voxClear(); + ClearPalManager(); TexMan.DeleteAll(); TileFiles.CloseAll(); // delete the texture data before shutting down graphics. - GLInterface.Deinit(); I_ShutdownGraphics(); freeallmodels(); if (gi) @@ -932,6 +935,12 @@ int RunGame() enginePreInit(); SetupGameButtons(); gameinfo.mBackButton = "engine/graphics/m_back.png"; + + GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes. + gi->loadPalette(); + voxInit(); + TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games. + engineInit(); gi->app_init(); CreateStatusBar(); SetDefaultMenuColors(); @@ -943,7 +952,22 @@ int RunGame() V_LoadTranslations(); // loading the translations must be delayed until the palettes have been fully set up. lookups.postLoadTables(); PostLoadSetup(); - videoInit(); + lookups.postLoadLookups(); + FMaterial::SetLayerCallback(setpalettelayer); + + V_Init2(); + twod->Begin(screen->GetWidth(), screen->GetHeight()); + twod->End(); + UpdateJoystickMenu(NULL); + UpdateVRModes(); + + setVideoMode(); + + LoadVoxelModels(); + GLInterface.Init(screen->GetWidth()); + screen->BeginFrame(); + screen->SetTextureFilterMode(); + setViewport(hud_size); D_CheckNetGame(); UpdateGenericUI(ui_generic); @@ -1011,7 +1035,7 @@ void updatePauseStatus() // //========================================================================== -void PolymostProcessVoxels(void); +void LoadVoxelModels(void); void setVideoMode() { @@ -1022,24 +1046,6 @@ void setVideoMode() videoClearScreen(0); } -void videoInit() -{ - lookups.postLoadLookups(); - V_Init2(); - setVideoMode(); - - PolymostProcessVoxels(); - GLInterface.Init(screen->GetWidth()); - screen->BeginFrame(); - screen->SetTextureFilterMode(); - setViewport(hud_size); -} - -void G_FatalEngineError(void) -{ - I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr); -} - //========================================================================== // // @@ -1326,27 +1332,50 @@ void DrawCrosshair(int deftile, int health, double xdelta, double ydelta, double void LoadDefinitions() { - loaddefinitionsfile("engine/engine.def"); // Internal stuff that is required. - - const char* defsfile = G_DefFile(); - cycle_t deftimer; deftimer.Reset(); deftimer.Clock(); - if (!loaddefinitionsfile(defsfile, true)) + const char* loaded = nullptr; + + const char* defsfile = G_DefFile(); + FString razedefsfile = defsfile; + razedefsfile.Substitute(".def", "-raze.def"); + + loaddefinitionsfile("engine/engine.def", false); // Internal stuff that is required. + + // check what we have. + // user .defs override the default ones and are not cumulative. + // if we fine even one Raze-specific file, all of those will be loaded cumulatively. + // otherwise the default rules inherited from older ports apply. + if (userConfig.UserDef.IsNotEmpty()) + { + if (!loaddefinitionsfile(userConfig.UserDef, true, false)) loaded = userConfig.UserDef; + } + else + { + if (fileSystem.FileExists(razedefsfile)) + { + if (!loaddefinitionsfile(razedefsfile, true, true)) loaded = razedefsfile; + } + else + { + if (!loaddefinitionsfile(defsfile, true, false)) loaded = defsfile; + } + } + + if (loaded) { deftimer.Unclock(); - Printf(PRINT_NONOTIFY, "Definitions file \"%s\" loaded in %.3f ms.\n", defsfile, deftimer.TimeMS()); + DPrintf(DMSG_SPAMMY, "Definitions file \"%s\" loaded, %f ms.\n", loaded, deftimer.TimeMS()); } userConfig.AddDefs.reset(); - // load the widescreen replacements last so that they do not clobber the CRC for the original items so that mod-side replacement are picked up. + // load the widescreen replacements last. This ensures that mods still get the correct CRCs for their own tile replacements. if (fileSystem.FindFile("engine/widescreen.def") >= 0 && !Args->CheckParm("-nowidescreen")) { loaddefinitionsfile("engine/widescreen.def"); } - - + fileSystem.InitHashChains(); // make sure that any resources that got added can be found again. } bool M_Active() @@ -1417,3 +1446,10 @@ DEFINE_GLOBAL(gameaction) DEFINE_GLOBAL(gamestate) DEFINE_GLOBAL(demoplayback) DEFINE_GLOBAL(consoleplayer) + + +void InitBuildTiles() +{ + // need to find a better way to handle this thing. +} + diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 3edbddf2f..4e130fdb9 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -65,6 +65,7 @@ struct UserConfig { FString gamegrp; FString CommandMap; + FString UserDef; FString DefaultDef; FString DefaultCon; FString CommandDemo; @@ -221,7 +222,6 @@ void S_PauseSound(bool notmusic, bool notsfx); void S_ResumeSound(bool notsfx); void S_SetSoundPaused(int state); -void G_FatalEngineError(void); enum { MaxSmoothRatio = FRACUNIT diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 61038ee88..23191157e 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -148,28 +148,6 @@ bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnu return true; } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -bool spriteIsModelOrVoxel(const spritetype * tspr) -{ - if ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].flags & SPREXT_NOTMD) - return false; - - if (hw_models) - { - auto& mdinfo = tile2model[Ptile2tile(tspr->picnum, tspr->pal)]; - if (mdinfo.modelid >= 0 && mdinfo.framenum >= 0) return true; - } - - auto slabalign = (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB; - if (r_voxels && !slabalign && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) return true; - return (slabalign && voxmodels[tspr->picnum]); -} - //========================================================================== // // note that this returns values in renderer coordinate space with inverted sign! @@ -213,10 +191,10 @@ void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool auto tex = tileGetTexture(spr->picnum); int width, leftofs; - if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - width = TileFiles.tiledata[spr->picnum].h_xsize; - leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset); + width = TileFiles.tiledata[spr->picnum].hiofs.xsize; + leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset); } else { @@ -249,12 +227,12 @@ void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool auto tex = tileGetTexture(spr->picnum); int width, height, leftofs, topofs; - if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - width = TileFiles.tiledata[spr->picnum].h_xsize * spr->xrepeat; - height = TileFiles.tiledata[spr->picnum].h_ysize * spr->yrepeat; - leftofs = (TileFiles.tiledata[spr->picnum].h_xoffs + spr->xoffset) * spr->xrepeat; - topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset) * spr->yrepeat; + width = TileFiles.tiledata[spr->picnum].hiofs.xsize * spr->xrepeat; + height = TileFiles.tiledata[spr->picnum].hiofs.ysize * spr->yrepeat; + leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset) * spr->xrepeat; + topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + spr->yoffset) * spr->yrepeat; } else { diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 5435325e6..f9f2432d9 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -7,7 +7,6 @@ extern int cameradist, cameraclock; bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio); -bool spriteIsModelOrVoxel(const spritetype* tspr); void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz); void setWallSectors(); void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render = false); diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index bbb3a1b5b..376ad9655 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -274,6 +274,18 @@ static void DeleteStuff(FileSystem &fileSystem, const TArray& deletelum // // //========================================================================== +const char* iwad_folders[13] = { "textures/", "hires/", "sounds/", "music/", "maps/" }; +const char* iwad_reserved_duke[12] = { ".map", ".con", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_blood[12] = { ".map", ".ini", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_sw[12] = { ".map", "swcustom.txt", "menudef", "gldefs", "zscript", "maps/", nullptr }; +const char* iwad_reserved_ex[12] = { ".map", "menudef", "gldefs", "zscript", "maps/", nullptr }; + +const char** iwad_reserved() +{ + return (g_gameType & GAMEFLAG_PSEXHUMED) ? iwad_reserved_ex : + (g_gameType & GAMEFLAG_SW) ? iwad_reserved_sw : + (g_gameType & GAMEFLAG_BLOOD) ? iwad_reserved_blood : iwad_reserved_duke; +} void InitFileSystem(TArray& groups) { @@ -374,6 +386,8 @@ void InitFileSystem(TArray& groups) } todelete.Append(userConfig.toBeDeleted); LumpFilterInfo lfi; + for (auto p : iwad_folders) lfi.reservedFolders.Push(p); + for (auto p = iwad_reserved(); *p; p++) lfi.requiredPrefixes.Push(*p); lfi.dotFilter = LumpFilter; diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 2aaf7fc6e..f3d44fab7 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -189,6 +189,7 @@ static void GameTicker() case ga_newgame: FX_StopAllSounds(); case ga_newgamenostopsound: + DeleteScreenJob(); newGameStarted = true; FX_SetReverb(0); gi->FreeLevelData(); diff --git a/source/core/mapinfo.cpp b/source/core/mapinfo.cpp index 506cae54c..609081f7f 100644 --- a/source/core/mapinfo.cpp +++ b/source/core/mapinfo.cpp @@ -38,6 +38,7 @@ #include "raze_music.h" #include "filesystem.h" #include "printf.h" +#include "raze_sound.h" FString gSkillNames[MAXSKILLS]; FString gVolumeNames[MAXVOLUMES]; @@ -109,7 +110,8 @@ bool SetMusicForMap(const char* mapname, const char* music, bool namehack) { if (!stricmp(mapname, specials[i])) { - // todo: store this properly. + if (specialmusic.Size() <= i) specialmusic.Resize(i + 1); + specialmusic[i] = music; return true; } } @@ -127,7 +129,7 @@ bool SetMusicForMap(const char* mapname, const char* music, bool namehack) if (numMatches != 4 || toupper(b1) != 'E' || toupper(b2) != 'L') return false; - index = FindMapByLevelNum(ep*100 + lev); + index = FindMapByLevelNum(levelnum(ep - 1, lev - 1)); } if (index != nullptr) diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 508a75db2..17f446aa7 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -742,3 +742,29 @@ DEFINE_ACTION_FUNCTION(_PlayerMenu, DrawPlayerSprite) return 0; } +#ifdef _WIN32 +EXTERN_CVAR(Bool, vr_enable_quadbuffered) +#endif + +void UpdateVRModes(bool considerQuadBuffered) +{ + FOptionValues** pVRModes = OptionValues.CheckKey("VRMode"); + if (pVRModes == nullptr) return; + + TArray& vals = (*pVRModes)->mValues; + TArray filteredValues; + int cnt = vals.Size(); + for (int i = 0; i < cnt; ++i) { + auto const& mode = vals[i]; + if (mode.Value == 7) { // Quad-buffered stereo +#ifdef _WIN32 + if (!vr_enable_quadbuffered) continue; +#else + continue; // Remove quad-buffered option on Mac and Linux +#endif + if (!considerQuadBuffered) continue; // Probably no compatible screen mode was found + } + filteredValues.Push(mode); + } + vals = filteredValues; +} diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h new file mode 100644 index 000000000..4704988e8 --- /dev/null +++ b/source/core/parsefuncs.h @@ -0,0 +1,406 @@ + +/* +** parsefuncs.h +** handlers for .def parser +** only to be included by the actual parser +** +**--------------------------------------------------------------------------- +** Copyright 2021 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor); +int tileSetSkybox(int picnum, int palnum, FString* facenames); +void tileRemoveReplacement(int num); + +//=========================================================================== +// +// +// +//=========================================================================== + +template +void parseSkip(FScanner& sc, FScriptPosition& pos) +{ + for (int i = 0; i < cnt; i++) if (!sc.GetString()) return; +} + +void parseDefine(FScanner& sc, FScriptPosition& pos) +{ + FString name; + if (!sc.GetString(name)) return; + if (!sc.GetNumber()) return; + sc.AddSymbol(name, sc.Number); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseDefineTexture(FScanner& sc, FScriptPosition& pos) +{ + int tile, palette; + + if (!sc.GetNumber(tile, true)) return; + if (!sc.GetNumber(palette, true)) return; + if (!sc.GetNumber(true)) return; //formerly x-center, unused + if (!sc.GetNumber(true)) return; //formerly y-center, unused + if (!sc.GetNumber(true)) return; //formerly x-size, unused + if (!sc.GetNumber(true)) return; //formerly y-size, unused + if (!sc.GetString()) return; + + tileSetHightileReplacement(tile, palette, sc.String, -1.0, 1.0, 1.0, 1.0, 1.0); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +static void parseTexturePaletteBlock(FScanner& sc, FScriptPosition& pos, int tile) +{ + FScanner::SavedPos blockend; + + int pal = -1, xsiz = 0, ysiz = 0; + FString fn; + double alphacut = -1.0, xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; + + if (!sc.GetNumber(pal, true)) return; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.GetString(); + if (sc.Compare("file")) sc.GetString(fn); + else if (sc.Compare("alphacut")) sc.GetFloat(alphacut, true); + else if (sc.Compare({ "xscale", "scale", "intensity", "detailscale" })) sc.GetFloat(xscale, true); // what's the point of all of these names? + else if (sc.Compare("yscale")) sc.GetFloat(yscale, true); + else if (sc.Compare({ "specpower", "specularpower", "parallaxscale" })) sc.GetFloat(specpower, true); + else if (sc.Compare({ "specfactor", "specularfactor", "parallaxbias" })) sc.GetFloat(specfactor, true); + else if (sc.Compare("orig_sizex")) sc.GetNumber(xsiz, true); + else if (sc.Compare("orig_sizey")) sc.GetNumber(ysiz, true); + }; + + if ((unsigned)tile < MAXUSERTILES) + { + if ((unsigned)pal >= MAXPALOOKUPS - RESERVEDPALS) + { + pos.Message(MSG_ERROR, "missing or invalid 'palette number' for texture definition"); + } + else if (fn.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing 'file name' for texture definition"); + } + else if (!fileSystem.FileExists(fn)) + { + pos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); + } + else + { + if (xsiz > 0 && ysiz > 0) + { + tileSetDummy(tile, xsiz, ysiz); + } + xscale = 1.0f / xscale; + yscale = 1.0f / yscale; + + tileSetHightileReplacement(tile, pal, fn, alphacut, xscale, yscale, specpower, specfactor); + } + } +} + +static void parseTextureSpecialBlock(FScanner& sc, FScriptPosition& pos, int tile, int specialpal) +{ + FScanner::SavedPos blockend; + + int pal = -1; + FString fn; + double xscale = 1.0, yscale = 1.0, specpower = 1.0, specfactor = 1.0; + + if (!sc.GetNumber(pal, true)) return; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.GetString(); + if (sc.Compare("file")) sc.GetString(fn); + else if (sc.Compare({ "xscale", "scale", "intensity", "detailscale" })) sc.GetFloat(xscale, true); // what's the point of all of these names? + else if (sc.Compare("yscale")) sc.GetFloat(yscale, true); + else if (sc.Compare({ "specpower", "specularpower", "parallaxscale" })) sc.GetFloat(specpower, true); + else if (sc.Compare({ "specfactor", "specularfactor", "parallaxbias" })) sc.GetFloat(specfactor, true); + }; + + if ((unsigned)tile < MAXUSERTILES) + { + if (fn.IsEmpty()) + { + pos.Message(MSG_ERROR, "missing 'file name' for texture definition"); + } + else if (!fileSystem.FileExists(fn)) + { + pos.Message(MSG_ERROR, "%s not found in replacement for tile %d", fn.GetChars(), tile); + } + else + { + if (pal == DETAILPAL) + { + xscale = 1.0f / xscale; + yscale = 1.0f / yscale; + } + + tileSetHightileReplacement(tile, pal, fn, -1.f, xscale, yscale, specpower, specfactor); + } + } +} + +void parseTexture(FScanner& sc, FScriptPosition& pos) +{ + FScanner::SavedPos blockend; + int tile = -1; + + if (!sc.GetNumber(tile, true)) return; + ValidateTilenum("texture", tile, pos); // do not abort, we still need to parse over the data. + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("pal")) parseTexturePaletteBlock(sc, pos, tile); + else if (sc.Compare("detail")) parseTextureSpecialBlock(sc, pos, tile, DETAILPAL); + else if (sc.Compare("glow")) parseTextureSpecialBlock(sc, pos, tile, GLOWPAL); + else if (sc.Compare("specular")) parseTextureSpecialBlock(sc, pos, tile, SPECULARPAL); + else if (sc.Compare("normal")) parseTextureSpecialBlock(sc, pos, tile, NORMALPAL); + } +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseDefineSkybox(FScanner& sc, FScriptPosition& pos) +{ + int tile, palette; + FString fn[6]; + + if (!sc.GetNumber(tile, true)) return; + if (!sc.GetNumber(palette, true)) return; + if (!sc.GetNumber(true)) return; //'future extension' (for what?) + for (int i = 0; i < 6; i++) + { + if (!sc.GetString()) return; + fn[i] = sc.String; + } + tileSetSkybox(tile, palette, fn); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseSkybox(FScanner& sc, FScriptPosition& pos) +{ + FString faces[6]; + FScanner::SavedPos blockend; + int tile = -1, pal = 0; + + if (sc.StartBraces(&blockend)) return; + while (!sc.FoundEndBrace(blockend)) + { + sc.MustGetString(); + if (sc.Compare("tile")) sc.GetNumber(tile, true); + else if (sc.Compare("pal")) sc.GetNumber(pal, true); + else if (sc.Compare({ "ft", "front", "forward" })) sc.GetString(faces[0]); + else if (sc.Compare({ "rt", "right" })) sc.GetString(faces[1]); + else if (sc.Compare({ "bk", "back" })) sc.GetString(faces[2]); + else if (sc.Compare({ "lt", "lf", "left" })) sc.GetString(faces[3]); + else if (sc.Compare({ "up", "ceiling", "top", "ceil" })) sc.GetString(faces[4]); + else if (sc.Compare({ "dn", "floor", "bottom", "down" })) sc.GetString(faces[5]); + // skip over everything else. + } + if (tile < 0) + { + pos.Message(MSG_ERROR, "skybox: missing tile number"); + return; + } + tileSetSkybox(tile, pal, faces); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseSetupTile(FScanner& sc, FScriptPosition& pos) +{ + int tile; + if (!sc.GetNumber(tile, true)) return; + if (!ValidateTilenum("setuptile", tile, pos)) return; + auto& tiled = TileFiles.tiledata[tile]; + if (!sc.GetNumber(tiled.hiofs.xsize, true)) return; + if (!sc.GetNumber(tiled.hiofs.ysize, true)) return; + if (!sc.GetNumber(tiled.hiofs.xoffs, true)) return; + if (!sc.GetNumber(tiled.hiofs.yoffs, true)) return; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseSetupTileRange(FScanner& sc, FScriptPosition& pos) +{ + int tilestart, tileend; + if (!sc.GetNumber(tilestart, true)) return; + if (!sc.GetNumber(tileend, true)) return; + if (!ValidateTileRange("setuptilerange", tilestart, tileend, pos)) return; + + TileOffs hiofs; + if (!sc.GetNumber(hiofs.xsize, true)) return; + if (!sc.GetNumber(hiofs.ysize, true)) return; + if (!sc.GetNumber(hiofs.xoffs, true)) return; + if (!sc.GetNumber(hiofs.yoffs, true)) return; + + for (int i = tilestart; i <= tileend; i++) TileFiles.tiledata[i].hiofs = hiofs; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseAnimTileRange(FScanner& sc, FScriptPosition& pos) +{ + SetAnim set; + if (!sc.GetNumber(set.tile1, true)) return; + if (!sc.GetNumber(set.tile2, true)) return; + if (!sc.GetNumber(set.speed, true)) return; + if (!sc.GetNumber(set.type, true)) return; + processSetAnim("animtilerange", pos, set); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseAlphahack(FScanner& sc, FScriptPosition& pos) +{ + int tile; + + if (!sc.GetNumber(tile, true)) return; + if (!sc.GetFloat(true)) return; + if ((unsigned)tile < MAXTILES) TileFiles.tiledata[tile].texture->alphaThreshold = (float)sc.Float; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseAlphahackRange(FScanner& sc, FScriptPosition& pos) +{ + int tilestart, tileend; + + if (!sc.GetNumber(tilestart, true)) return; + if (!sc.GetNumber(tileend, true)) return; + if (!sc.GetFloat(true)) return; + if (!ValidateTileRange("alphahackrange", tilestart, tileend, pos)) return; + + for (int i = tilestart; i <= tileend; i++) + TileFiles.tiledata[i].texture->alphaThreshold = (float)sc.Number; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseDefineTint(FScanner& sc, FScriptPosition& pos) +{ + int pal, r, g, b, f; + + if (!sc.GetNumber(pal, true)) return; + if (!sc.GetNumber(r)) return; + if (!sc.GetNumber(g)) return; + if (!sc.GetNumber(b)) return; + if (!sc.GetNumber(f)) return; + lookups.setPaletteTint(pal, r, g, b, 0, 0, 0, f); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseFogpal(FScanner& sc, FScriptPosition& pos) +{ + int pal, r, g, b; + + if (!sc.GetNumber(pal, true)) return; + if (!sc.GetNumber(r)) return; + if (!sc.GetNumber(g)) return; + if (!sc.GetNumber(b)) return; + + r = clamp(r, 0, 63); + g = clamp(g, 0, 63); + b = clamp(b, 0, 63); + + lookups.makeTable(pal, nullptr, r << 2, g << 2, b << 2, 1); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void parseNoFloorpalRange(FScanner& sc, FScriptPosition& pos) +{ + int start, end; + if (!sc.GetNumber(start, true)) return; + if (!sc.GetNumber(end, true)) return; + if (start > 1) start = 1; + if (end > MAXPALOOKUPS - 1) end = MAXPALOOKUPS - 1; + for (int i = start; i <= end; i++) + lookups.tables[i].noFloorPal = true; +} diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index 9ee2d1c72..c23f0b0ff 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -46,6 +46,7 @@ static bool mus_blocked; static FString lastStartedMusic; +TArray specialmusic; MusicAliasMap MusicAliases; MusicAliasMap LevelMusicAliases; @@ -132,23 +133,27 @@ FileReader OpenMusic(const char* musicname) if (!reader.isOpen()) { int lumpnum = LookupMusic(musicname); - if (mus_extendedlookup && lumpnum >= 0) - { - // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. - auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); - auto rfbase = ExtractFileBase(rfn); - FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); - lumpnum = LookupMusic(aliasMusicname); - } - if (lumpnum == -1) + if (mus_extendedlookup || lumpnum < 0) { + if (lumpnum >= 0) + { + // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. + auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); + auto rfbase = ExtractFileBase(rfn); + FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); + int newlumpnum = LookupMusic(aliasMusicname); + if (newlumpnum >= 0) lumpnum = newlumpnum; + } + // Always look in the 'music' subfolder as well. This gets used by multiple setups to store ripped CD tracks. FStringf aliasMusicname("music/%s", musicname); - lumpnum = LookupMusic(aliasMusicname); + int newlumpnum = LookupMusic(aliasMusicname, lumpnum >= 0); + if (newlumpnum >= 0) lumpnum = newlumpnum; } + if (lumpnum == -1 && (g_gameType & GAMEFLAG_SW)) { - // Some Shadow Warrioe distributions have the music in a subfolder named 'classic'. Check that, too. + // Some Shadow Warrior distributions have the music in a subfolder named 'classic'. Check that, too. FStringf aliasMusicname("classic/music/%s", musicname); lumpnum = fileSystem.FindFile(aliasMusicname); } diff --git a/source/core/raze_music.h b/source/core/raze_music.h index a9051d650..a87644406 100644 --- a/source/core/raze_music.h +++ b/source/core/raze_music.h @@ -6,6 +6,7 @@ typedef TMap MusicAliasMap; extern MusicAliasMap MusicAliases; +extern TArray specialmusic; // Totally minimalistic interface - should be all the game modules need. void Mus_InitMusic(); diff --git a/source/core/raze_sound.cpp b/source/core/raze_sound.cpp index 4020f1b0a..463fece92 100644 --- a/source/core/raze_sound.cpp +++ b/source/core/raze_sound.cpp @@ -142,7 +142,11 @@ int S_LookupSound(const char* fn) static const char * const sndformats[] = { "OGG", "FLAC", "WAV" }; if (snd_extendedlookup) { - int lump = fileSystem.FindFileWithExtensions(StripExtension(fn), sndformats, countof(sndformats)); + auto newfn = StripExtension(fn); + int lump = fileSystem.FindFileWithExtensions(newfn, sndformats, countof(sndformats)); + if (lump >= 0) return lump; + newfn = "sound/" + newfn; + lump = fileSystem.FindFileWithExtensions(newfn, sndformats, countof(sndformats)); if (lump >= 0) return lump; } return fileSystem.FindFile(fn); diff --git a/source/glbackend/gl_palmanager.cpp b/source/core/rendering/hw_palmanager.cpp similarity index 87% rename from source/glbackend/gl_palmanager.cpp rename to source/core/rendering/hw_palmanager.cpp index aee5dade4..0298aa657 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/core/rendering/hw_palmanager.cpp @@ -35,7 +35,7 @@ #include #include "m_crc32.h" -#include "glbackend.h" +#include "hw_palmanager.h" #include "resourcefile.h" #include "imagehelpers.h" @@ -44,6 +44,8 @@ #include "build.h" #include "v_video.h" +static PaletteManager* palmanager; + //=========================================================================== // // This class manages the hardware data for the indexed render mode. @@ -138,4 +140,24 @@ IHardwareTexture* PaletteManager::GetLookup(int index) return nullptr; } +//=========================================================================== +// +// +// +//=========================================================================== +IHardwareTexture *setpalettelayer(int layer, int translation) +{ + if (!palmanager) palmanager = new PaletteManager; + if (layer == 1) + return palmanager->GetPalette(GetTranslationType(translation) - Translation_Remap); + else if (layer == 2) + return palmanager->GetLookup(GetTranslationIndex(translation)); + else return nullptr; +} + +void ClearPalManager() +{ + if (palmanager) delete palmanager; + palmanager = nullptr; +} \ No newline at end of file diff --git a/source/core/rendering/hw_palmanager.h b/source/core/rendering/hw_palmanager.h new file mode 100644 index 000000000..e308f79ab --- /dev/null +++ b/source/core/rendering/hw_palmanager.h @@ -0,0 +1,24 @@ +#pragma once + +#include "gl_hwtexture.h" + +struct palette_t; + +class PaletteManager +{ + IHardwareTexture* palettetextures[256] = {}; + IHardwareTexture* lookuptextures[256] = {}; + + unsigned FindPalswap(const uint8_t* paldata, palette_t& fadecolor); + +public: + ~PaletteManager(); + void DeleteAll(); + IHardwareTexture *GetPalette(int index); + IHardwareTexture* GetLookup(int index); +}; + + +IHardwareTexture* setpalettelayer(int layer, int translation); +void ClearPalManager(); + diff --git a/source/core/rendering/hw_voxels.cpp b/source/core/rendering/hw_voxels.cpp new file mode 100644 index 000000000..7ee3cbc6a --- /dev/null +++ b/source/core/rendering/hw_voxels.cpp @@ -0,0 +1,114 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2021 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** hw_voxels.cpp +** +** voxel handling. +** +**/ + +#include "build.h" +#include "voxels.h" +#include "hw_voxels.h" +#include "gamecontrol.h" + +int16_t tiletovox[MAXTILES]; +static int voxlumps[MAXVOXELS]; +float voxscale[MAXVOXELS]; +voxmodel_t* voxmodels[MAXVOXELS]; +FixedBitArray voxrotate; + + +void voxInit() +{ + for (auto& v : tiletovox) v = -1; + for (auto& v : voxscale) v = 1.f; + voxrotate.Zero(); +} + +void voxClear() +{ + for (auto& vox : voxmodels) + { + if (vox) delete vox; + vox = nullptr; + } +} + +int voxDefine(int voxindex, const char* filename) +{ + if ((unsigned)voxindex >= MAXVOXELS) + return -1; + + int i = fileSystem.FindFile(filename); + voxlumps[voxindex] = i; + return i < 0 ? -1 : 0; +} + +static voxmodel_t* voxload(int lumpnum) +{ + FVoxel* voxel = R_LoadKVX(lumpnum); + if (voxel != nullptr) + { + voxmodel_t* vm = new voxmodel_t; + *vm = {}; + auto pivot = voxel->Mips[0].Pivot; + vm->mdnum = 1; //VOXel model id + vm->scale = vm->bscale = 1.f; + vm->piv.x = float(pivot.X); + vm->piv.y = float(pivot.Y); + vm->piv.z = float(pivot.Z); + vm->siz.x = voxel->Mips[0].SizeX; + vm->siz.y = voxel->Mips[0].SizeY; + vm->siz.z = voxel->Mips[0].SizeZ; + vm->is8bit = true; + voxel->Mips[0].Pivot.Zero(); // Needs to be taken out of the voxel data because it gets baked into the vertex buffer which we cannot use here. + vm->model = new FVoxelModel(voxel, true); + return vm; + } + return nullptr; +} + +void LoadVoxelModels() +{ + for (int i = 0; i < MAXVOXELS; i++) + { + int lumpnum = voxlumps[i]; + if (lumpnum > 0) + { + voxmodels[i] = voxload(lumpnum); + if (voxmodels[i]) + voxmodels[i]->scale = voxscale[i]; + else + Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum)); + } + else + { + auto index = fileSystem.FindResource(i, "KVX"); + if (index >= 0) + { + voxmodels[i] = voxload(index); + } + } + } +} + diff --git a/source/core/rendering/hw_voxels.h b/source/core/rendering/hw_voxels.h new file mode 100644 index 000000000..1633d1808 --- /dev/null +++ b/source/core/rendering/hw_voxels.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "mdsprite.h" + +// We still need the relation to mdmodel_t as long as the model code hasn't been redone. +struct voxmodel_t : public mdmodel_t +{ + FVoxelModel* model = nullptr; + vec3_t siz; + vec3f_t piv; + int32_t is8bit; +}; + + + +extern int16_t tiletovox[]; +extern float voxscale[]; +extern voxmodel_t* voxmodels[MAXVOXELS]; +extern FixedBitArray voxrotate; + +void voxInit(); +void voxClear(); +int voxDefine(int voxindex, const char* filename); diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 86f2985d2..4f66ef393 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -40,6 +40,7 @@ #include "gamefuncs.h" #include "hw_portal.h" #include "gamestruct.h" +#include "hw_voxels.h" //========================================================================== @@ -48,8 +49,10 @@ // //========================================================================== -void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view) +void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view, binangle a1, binangle a2) { + ang1 = a1; + ang2 = a2; di = _di; clipper = c; viewx = view.x * (1/ 16.f); @@ -82,6 +85,8 @@ void BunchDrawer::StartScene() Bunches.Clear(); CompareData.Clear(); gotsector.Zero(); + gotsector2.Zero(); + gotwall.Zero(); } //========================================================================== @@ -90,14 +95,16 @@ void BunchDrawer::StartScene() // //========================================================================== -void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan) +bool BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal) { FBunch* bunch = &Bunches[LastBunch = Bunches.Reserve(1)]; bunch->sectnum = sectnum; bunch->startline = bunch->endline = linenum; - bunch->startangle = startan; - bunch->endangle = endan; + bunch->startangle = (startan.asbam() - ang1.asbam()) > ANGLE_180? ang1 :startan; + bunch->endangle = (endan.asbam() - ang2.asbam()) < ANGLE_180 ? ang2 : endan; + bunch->portal = portal; + return bunch->endangle != ang2; } //========================================================================== @@ -106,10 +113,11 @@ void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangl // //========================================================================== -void BunchDrawer::AddLineToBunch(int line, binangle newan) +bool BunchDrawer::AddLineToBunch(int line, binangle newan) { Bunches[LastBunch].endline++; - Bunches[LastBunch].endangle = newan; + Bunches[LastBunch].endangle = (newan.asbam() - ang2.asbam()) < ANGLE_180 ? ang2 : newan; + return Bunches[LastBunch].endangle != ang2; } //========================================================================== @@ -181,7 +189,7 @@ bool BunchDrawer::CheckClip(walltype* wal) // //========================================================================== -int BunchDrawer::ClipLine(int line) +int BunchDrawer::ClipLine(int line, bool portal) { auto wal = &wall[line]; @@ -194,7 +202,7 @@ int BunchDrawer::ClipLine(int line) return CL_Skip; } - if (!clipper->SafeCheckRange(startAngle, endAngle)) + if (!portal && !clipper->SafeCheckRange(startAngle, endAngle)) { return CL_Skip; } @@ -202,7 +210,7 @@ int BunchDrawer::ClipLine(int line) if (wal->nextwall == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal)) { // one-sided - clipper->SafeAddClipRange(startAngle, endAngle); + if (!portal) clipper->SafeAddClipRange(startAngle, endAngle); return CL_Draw; } else @@ -224,14 +232,15 @@ void BunchDrawer::ProcessBunch(int bnch) ClipWall.Clock(); for (int i = bunch->startline; i <= bunch->endline; i++) { - int clipped = ClipLine(i); + int clipped = ClipLine(i, bunch->portal); if (clipped & CL_Draw) { show2dwall.Set(i); - //if (gl_render_walls) + if (!gotwall[i]) { + gotwall.Set(i); ClipWall.Unclock(); Bsp.Unclock(); SetupWall.Clock(); @@ -249,7 +258,7 @@ void BunchDrawer::ProcessBunch(int bnch) if (clipped & CL_Pass) { ClipWall.Unclock(); - ProcessSector(wall[i].nextsector); + ProcessSector(wall[i].nextsector, false); ClipWall.Clock(); } } @@ -288,7 +297,7 @@ int BunchDrawer::WallInFront(int wall1, int wall2) if ((t1 * t2) >= 0) { t2 = PointOnLineSide(viewx, viewy, x1s, y1s, dx, dy); - return((t2 * t1) < 0); + return((t2 * t1) <= 0); } dx = x2e - x2s; @@ -304,7 +313,7 @@ int BunchDrawer::WallInFront(int wall1, int wall2) if ((t1 * t2) >= 0) { t2 = PointOnLineSide(viewx, viewy, x2s, y2s, dx, dy); - return((t2 * t1) >= 0); + return((t2 * t1) > 0); } return(-2); } @@ -415,6 +424,7 @@ int BunchDrawer::FindClosestBunch() } } + //Printf("picked bunch starting at %d\n", Bunches[closest].startline); return closest; } @@ -424,10 +434,10 @@ int BunchDrawer::FindClosestBunch() // //========================================================================== -void BunchDrawer::ProcessSector(int sectnum) +void BunchDrawer::ProcessSector(int sectnum, bool portal) { - if (gotsector[sectnum]) return; - gotsector.Set(sectnum); + if (gotsector2[sectnum]) return; + gotsector2.Set(sectnum); auto sect = §or[sectnum]; bool inbunch; @@ -436,28 +446,32 @@ void BunchDrawer::ProcessSector(int sectnum) SetupSprite.Clock(); int z; - SectIterator it(sectnum); - while ((z = it.NextIndex()) >= 0) + if (!gotsector[sectnum]) { - auto const spr = (uspriteptr_t)&sprite[z]; - - if ((spr->cstat & CSTAT_SPRITE_INVISIBLE) || spr->xrepeat == 0 || spr->yrepeat == 0) // skip invisible sprites - continue; - - int sx = spr->x - iview.x, sy = spr->y - int(iview.y); - - // this checks if the sprite is it behind the camera, which will not work if the pitch is high enough to necessitate a FOV of more than 180°. - //if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) || (hw_models && tile2model[spr->picnum].modelid >= 0) || ((sx * gcosang) + (sy * gsinang) > 0)) + gotsector.Set(sectnum); + SectIterator it(sectnum); + while ((z = it.NextIndex()) >= 0) { - if ((spr->cstat & (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_MASK)) != (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_WALL) || - (r_voxels && tiletovox[spr->picnum] >= 0 && voxmodels[tiletovox[spr->picnum]]) || - (r_voxels && gi->Voxelize(spr->picnum)) || - DMulScale(bcos(spr->ang), -sx, bsin(spr->ang), -sy, 6) > 0) - if (renderAddTsprite(di->tsprite, di->spritesortcnt, z, sectnum)) - break; + auto const spr = (uspriteptr_t)&sprite[z]; + + if ((spr->cstat & CSTAT_SPRITE_INVISIBLE) || spr->xrepeat == 0 || spr->yrepeat == 0) // skip invisible sprites + continue; + + int sx = spr->x - iview.x, sy = spr->y - int(iview.y); + + // this checks if the sprite is it behind the camera, which will not work if the pitch is high enough to necessitate a FOV of more than 180°. + //if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) || (hw_models && tile2model[spr->picnum].modelid >= 0) || ((sx * gcosang) + (sy * gsinang) > 0)) + { + if ((spr->cstat & (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_MASK)) != (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_WALL) || + (r_voxels && tiletovox[spr->picnum] >= 0 && voxmodels[tiletovox[spr->picnum]]) || + (r_voxels && gi->Voxelize(spr->picnum)) || + DMulScale(bcos(spr->ang), -sx, bsin(spr->ang), -sy, 6) > 0) + if (renderAddTsprite(di->tsprite, di->spritesortcnt, z, sectnum)) + break; + } } + SetupSprite.Unclock(); } - SetupSprite.Unclock(); if (automapping) show2dsector.Set(sectnum); @@ -478,36 +492,26 @@ void BunchDrawer::ProcessSector(int sectnum) DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) }; DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) }; #endif - binangle ang1 = thiswall->clipangle; - binangle ang2 = wall[thiswall->point2].clipangle; + binangle walang1 = thiswall->clipangle; + binangle walang2 = wall[thiswall->point2].clipangle; - if (ang1.asbam() - ang2.asbam() < ANGLE_180) + // outside the visible area or seen from the backside. + if ((walang1.asbam() - ang1.asbam() > ANGLE_180 && walang2.asbam() - ang1.asbam() > ANGLE_180) || + (walang1.asbam() - ang2.asbam() < ANGLE_180 && walang2.asbam() - ang2.asbam() < ANGLE_180) || + (walang1.asbam() - walang2.asbam() < ANGLE_180)) { - // Backside inbunch = false; } - /* disabled because it only fragments the bunches without any performance gain. - else if (!clipper->SafeCheckRange(ang1, ang2)) + else if (!inbunch) { - // is it visible? - inbunch = false; - } - */ - else if (!inbunch || ang2.asbam() - startangle.asbam() >= ANGLE_180) - { - // don't let a bunch span more than 180° to avoid problems. - // This limitation ensures that the combined range of 2 - // bunches will always be less than 360° which simplifies - // the distance comparison code because it prevents a - // situation where 2 bunches may overlap at both ends. - - startangle = ang1; - StartBunch(sectnum, sect->wallptr + i, ang1, ang2); - inbunch = true; + startangle = walang1; + //Printf("Starting bunch:\n\tWall %d\n", sect->wallptr + i); + inbunch = StartBunch(sectnum, sect->wallptr + i, walang1, walang2, portal); } else { - AddLineToBunch(sect->wallptr + i, ang2); + //Printf("\tWall %d\n", sect->wallptr + i); + inbunch = AddLineToBunch(sect->wallptr + i, walang2); } if (thiswall->point2 != sect->wallptr + i + 1) inbunch = false; } @@ -519,16 +523,39 @@ void BunchDrawer::ProcessSector(int sectnum) // //========================================================================== -void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount) +void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal) { - Bsp.Clock(); - for(unsigned i=0;i 0) + //Printf("----------------------------------------- \nstart at sector %d\n", viewsectors[0]); + auto process = [&]() { - int closest = FindClosestBunch(); - ProcessBunch(closest); - DeleteBunch(closest); + for (unsigned i = 0; i < sectcount; i++) + ProcessSector(viewsectors[i], portal); + while (Bunches.Size() > 0) + { + int closest = FindClosestBunch(); + ProcessBunch(closest); + DeleteBunch(closest); + } + }; + + Bsp.Clock(); + if (ang1.asbam() != 0 || ang2.asbam() != 0) + { + process(); + } + else + { + // with a 360° field of view we need to split the scene into two halves. + // The BunchInFront check can fail with angles that may wrap around. + auto rotang = di->Viewpoint.RotAngle; + ang1 = bamang(rotang - ANGLE_90); + ang2 = bamang(rotang + ANGLE_90); + process(); + clipper->Clear(); + gotsector2.Zero(); + ang1 = bamang(rotang + ANGLE_90); + ang2 = bamang(rotang - ANGLE_90); + process(); } Bsp.Unclock(); } diff --git a/source/core/rendering/scene/hw_bunchdrawer.h b/source/core/rendering/scene/hw_bunchdrawer.h index dbf5329eb..d8906c6c8 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.h +++ b/source/core/rendering/scene/hw_bunchdrawer.h @@ -11,7 +11,8 @@ struct FBunch int sectnum; int startline; int endline; - binangle startangle; // in pseudo angles for the clipper + bool portal; + binangle startangle; binangle endangle; }; @@ -27,6 +28,9 @@ class BunchDrawer vec2_t iview; float gcosang, gsinang; FixedBitArray gotsector; + FixedBitArray gotsector2; + FixedBitArray gotwall; + binangle ang1, ang2; private: @@ -38,19 +42,19 @@ private: }; void StartScene(); - void StartBunch(int sectnum, int linenum, binangle startan, binangle endan); - void AddLineToBunch(int line, binangle newan); + bool StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal); + bool AddLineToBunch(int line, binangle newan); void DeleteBunch(int index); bool CheckClip(walltype* wal); - int ClipLine(int line); + int ClipLine(int line, bool portal); void ProcessBunch(int bnch); int WallInFront(int wall1, int wall2); int BunchInFront(FBunch* b1, FBunch* b2); int FindClosestBunch(); - void ProcessSector(int sectnum); + void ProcessSector(int sectnum, bool portal); public: - void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view); - void RenderScene(const int* viewsectors, unsigned sectcount); + void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view, binangle a1, binangle a2); + void RenderScene(const int* viewsectors, unsigned sectcount, bool portal); const FixedBitArray& GotSector() const { return gotsector; } }; diff --git a/source/core/rendering/scene/hw_clipper.cpp b/source/core/rendering/scene/hw_clipper.cpp index 13476a747..124bea91c 100644 --- a/source/core/rendering/scene/hw_clipper.cpp +++ b/source/core/rendering/scene/hw_clipper.cpp @@ -358,29 +358,6 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end) // //----------------------------------------------------------------------------- -binangle Clipper::PointToAngle(const vec2_t& pos) -{ - vec2_t vec = pos - viewpoint; -#if 0 - - if (vec.x == 0 && vec.y == 0) - { - return 0; - } - else - { - double result = vec.y / double(abs(vec.x) + fabs(vec.y)); - if (vec.x < 0) - { - result = 2. - result; - } - return bamang(xs_Fix<30>::ToFix(result)); - } -#else - return q16ang(gethiq16angle(vec.x, vec.y)); -#endif -} - void Clipper::DumpClipper() { for (auto node = cliphead; node; node = node->next) diff --git a/source/core/rendering/scene/hw_clipper.h b/source/core/rendering/scene/hw_clipper.h index e19a01136..5c1280d5b 100644 --- a/source/core/rendering/scene/hw_clipper.h +++ b/source/core/rendering/scene/hw_clipper.h @@ -144,7 +144,29 @@ public: void DumpClipper(); - binangle PointToAngle(const vec2_t& point); + binangle PointToAngle(const vec2_t& pos) + { + vec2_t vec = pos - viewpoint; +#if 0 + + if (vec.x == 0 && vec.y == 0) + { + return bamang(0); + } + else + { + double result = vec.y / double(abs(vec.x) + fabs(vec.y)); + if (vec.x < 0) + { + result = 2. - result; + } + return bamang(xs_Fix<30>::ToFix(result)); + } +#else + return bvectangbam(vec.x, vec.y); +#endif + } + }; diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index 74905bcd3..196734a83 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -41,6 +41,7 @@ #include "gamecvars.h" #include "gamestruct.h" #include "automap.h" +#include "hw_voxels.h" EXTERN_CVAR(Float, r_visibility) CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -210,7 +211,7 @@ angle_t HWDrawInfo::FrustumAngle() // but at least it doesn't overestimate too much... double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0; angle_t a1 = DAngle(floatangle).BAMs(); - if (a1 >= ANGLE_180) return 0xffffffff; + if (a1 >= ANGLE_90) return 0xffffffff; // it's either below 90 or bust. return a1; } @@ -300,14 +301,14 @@ void HWDrawInfo::DispatchSprites() { HWSprite hwsprite; int num = tiletovox[tspr->picnum]; - if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, §or[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7)))) + if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, §or[tspr->sectnum], voxrotate[num])) continue; } else if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum]) { HWSprite hwsprite; int num = tspr->picnum; - hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, §or[tspr->sectnum], voxrotate[num >> 3] & (1 << (num & 7))); + hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, §or[tspr->sectnum], voxrotate[num]); continue; } } @@ -363,12 +364,12 @@ void HWDrawInfo::DispatchSprites() // //----------------------------------------------------------------------------- -void HWDrawInfo::CreateScene() +void HWDrawInfo::CreateScene(bool portal) { const auto& vp = Viewpoint; angle_t a1 = FrustumAngle(); - mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); + if (a1 != 0xffffffff) mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); // reset the portal manager portalState.StartFrame(); @@ -384,11 +385,12 @@ void HWDrawInfo::CreateScene() geoofs = { 0,0 }; vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) }; - mDrawer.Init(this, mClipper, view); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); if (vp.SectNums) - mDrawer.RenderScene(vp.SectNums, vp.SectCount); + mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal); else - mDrawer.RenderScene(&vp.SectCount, 1); + mDrawer.RenderScene(&vp.SectCount, 1, portal); SetupSprite.Clock(); gi->processSprites(tsprite, spritesortcnt, view.x, view.y, vp.Pos.Z * -256, bamang(vp.RotAngle), vp.TicFrac * 65536); @@ -420,8 +422,9 @@ void HWDrawInfo::CreateScene() mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); - mDrawer.Init(this, mClipper, view); - mDrawer.RenderScene(&drawsect, 1); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); + mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) { @@ -451,8 +454,9 @@ void HWDrawInfo::CreateScene() mClipper->Clear(); mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1)); - mDrawer.Init(this, mClipper, view); - mDrawer.RenderScene(&drawsect, 1); + if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); + else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); + mDrawer.RenderScene(&drawsect, 1, false); for (int i = 0; i < eff.geocnt; i++) { @@ -669,7 +673,7 @@ void HWDrawInfo::Set3DViewport(FRenderState &state) // //----------------------------------------------------------------------------- -void HWDrawInfo::DrawScene(int drawmode) +void HWDrawInfo::DrawScene(int drawmode, bool portal) { static int recursion = 0; static int ssao_portals_available = 0; @@ -691,7 +695,7 @@ void HWDrawInfo::DrawScene(int drawmode) ssao_portals_available--; } - CreateScene(); + CreateScene(portal); auto& RenderState = *screen->RenderState(); RenderState.SetDepthMask(true); @@ -724,7 +728,7 @@ void HWDrawInfo::DrawScene(int drawmode) void HWDrawInfo::ProcessScene(bool toscreen) { portalState.BeginScene(); - DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN); + DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN, false); if (toscreen && isBlood()) { gotsector = mDrawer.GotSector(); // Blood needs this to implement some lighting effect hacks. Needs to be refactored to use better info. diff --git a/source/core/rendering/scene/hw_drawinfo.h b/source/core/rendering/scene/hw_drawinfo.h index dc223ed21..9e7995f0a 100644 --- a/source/core/rendering/scene/hw_drawinfo.h +++ b/source/core/rendering/scene/hw_drawinfo.h @@ -158,8 +158,8 @@ public: void ClearBuffers(); HWDrawInfo *EndDrawInfo(); - void DrawScene(int drawmode); - void CreateScene(); + void DrawScene(int drawmode, bool portal); + void CreateScene(bool portal); void DispatchSprites(); void RenderScene(FRenderState &state); void RenderTranslucent(FRenderState &state); diff --git a/source/core/rendering/scene/hw_drawlistadd.cpp b/source/core/rendering/scene/hw_drawlistadd.cpp index 26ef3da57..69fb35222 100644 --- a/source/core/rendering/scene/hw_drawlistadd.cpp +++ b/source/core/rendering/scene/hw_drawlistadd.cpp @@ -95,7 +95,7 @@ void HWDrawInfo::AddFlat(HWFlat *flat) { int list;; - if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON) // flat->texture->GetTranslucency() - fixme + if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON || checkTranslucentReplacement(flat->texture->GetID(), flat->palette)) { // translucent portals go into the translucent border list. list = flat->sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index e987adbc7..8b051fac7 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -11,6 +11,9 @@ #include "gamefuncs.h" #include "render.h" #include "matrix.h" +#include "gamecontrol.h" +#include "hw_renderstate.h" +#include "hw_cvars.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -26,6 +29,7 @@ struct FDynLightData; class VSMatrix; struct FSpriteModelFrame; class FRenderState; +struct voxmodel_t; struct HWSectorPlane { @@ -192,7 +196,6 @@ public: void SetupLights(HWDrawInfo *di, FDynLightData &lightdata); void MakeVertices(HWDrawInfo *di, bool nosplit); - void SetLightAndFog(FRenderState& state); void SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowmirror); void SkyLine(HWDrawInfo *di, sectortype *sec, walltype *line); @@ -356,3 +359,71 @@ inline float sectorVisibility(sectortype* sec) } inline const float hw_density = 0.35f; + +int checkTranslucentReplacement(FTextureID picnum, int pal); + +inline bool maskWallHasTranslucency(const walltype* wall) +{ + return (wall->cstat & CSTAT_WALL_TRANSLUCENT) || checkTranslucentReplacement(tileGetTexture(wall->picnum)->GetID(), wall->pal); +} + +inline bool spriteHasTranslucency(const spritetype* tspr) +{ + if ((tspr->cstat & CSTAT_SPRITE_TRANSLUCENT) || //(tspr->clipdist & TSPR_FLAGS_DRAW_LAST) || + ((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].alpha)) + return true; + + return checkTranslucentReplacement(tileGetTexture(tspr->picnum)->GetID(), tspr->pal); +} + +inline void SetSpriteTranslucency(const spritetype* sprite, float& alpha, FRenderStyle& RenderStyle) +{ + bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); + if (trans) + { + RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); + alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); + } + else + { + RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = 1.f; + } + alpha *= 1.f - spriteext[sprite->owner].alpha; +} + +//========================================================================== +// +// +// +//========================================================================== +extern PalEntry GlobalMapFog; +extern float GlobalFogDensity; + +__forceinline void SetLightAndFog(FRenderState& state, PalEntry fade, int palette, int shade, int visibility, float alpha, bool setcolor = true) +{ + // Fog must be done before the texture so that the texture selector can override it. + bool foggy = (GlobalMapFog || (fade & 0xffffff)); + auto ShadeDiv = lookups.tables[palette].ShadeFactor; + shade = clamp(shade, 0, numshades - 1); + // Disable brightmaps if non-black fog is used. + if (ShadeDiv >= 1 / 1000.f && foggy) + { + state.EnableFog(1); + float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); + state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); + state.SetSoftLightLevel(255); + state.SetLightParms(128.f, 1 / 1000.f); + } + else + { + state.EnableFog(0); + state.SetFog(0, 0); + state.SetSoftLightLevel(gl_fogmode != 0 && ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); + state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); + } + + // The shade rgb from the tint is ignored here. + state.SetColor(globalr * (1 / 255.f), globalg * (1 / 255.f), globalb * (1 / 255.f), alpha); +} + diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index a964e9aaa..71a1f50e7 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -41,9 +41,6 @@ CVAR(Int, gl_breaksec, -1, 0) #endif -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - //========================================================================== // // @@ -124,8 +121,8 @@ void HWFlat::MakeVertices() auto ret = screen->mVertexData->AllocVertices(6); auto vp = ret.first; - float x = !(sprite->cstat & CSTAT_SECTOR_XFLIP) ? 0.f : 1.f; - float y = !(sprite->cstat & CSTAT_SECTOR_YFLIP) ? 0.f : 1.f; + float x = !(sprite->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; + float y = !(sprite->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; for (unsigned i = 0; i < 6; i++) { const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 }; @@ -170,28 +167,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) else state.SetNormal({ 0, -1, 0 }); } - // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; - // Disable brightmaps if non-black fog is used. - if (ShadeDiv >= 1 / 1000.f && foggy) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); - } - - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(PalEntry(255, globalr, globalg, globalb), alpha); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); if (translucent) { @@ -202,7 +178,8 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_GEqual, 0.f); } state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr? CLAMP_NONE : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); @@ -366,7 +343,7 @@ void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* s z = sprite->z * (1 / -256.f); if (z == di->Viewpoint.Pos.Z) return; // looking right at the edge. - visibility = sectorVisibility(§or[sprite->sectnum]);// *(4.f / 5.f); // The factor comes directly from Polymost. No idea why this uses a different visibility setting. Bad projection math? + visibility = sectorVisibility(§or[sprite->sectnum]) *(4.f / 5.f); // The factor comes directly from Polymost. What is it with Build and these magic factors? // Weird Build logic that really makes no sense. if ((sprite->cstat & CSTAT_SPRITE_ONE_SIDED) != 0 && (di->Viewpoint.Pos.Z < z) == ((sprite->cstat & CSTAT_SPRITE_YFLIP) == 0)) @@ -380,17 +357,8 @@ void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* s palette = sprite->pal; fade = lookups.getFade(sector[sprite->sectnum].floorpal); // fog is per sector. - bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(sprite, alpha, RenderStyle); + PutFlat(di, 0); } } diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index 5d97679ba..cf35cc320 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -400,9 +400,10 @@ void HWScenePortalBase::DrawContents(HWDrawInfo* di, FRenderState& state) { if (Setup(di, state, di->mClipper)) { - gi->EnterPortal(di->Viewpoint.CameraSprite, GetType()); - di->DrawScene(DM_PORTAL); - gi->LeavePortal(di->Viewpoint.CameraSprite, GetType()); + auto type = GetType(); + gi->EnterPortal(di->Viewpoint.CameraSprite, type); + di->DrawScene(DM_PORTAL, type == PORTAL_SECTOR_CEILING); + gi->LeavePortal(di->Viewpoint.CameraSprite, type); Shutdown(di, state); } else state.ClearScreen(); @@ -430,8 +431,8 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) clipper->SafeAddClipRange(bamang(0), bamang(0xffffffff)); for (unsigned int i = 0; i < lines.Size(); i++) { - binangle startang = q16ang(gethiq16angle(lines[i].seg->x - view.x, lines[i].seg->y - view.y)); - binangle endang = q16ang(gethiq16angle(wall[lines[i].seg->point2].x - view.x, wall[lines[i].seg->point2].y - view.y)); + binangle startang = bvectangbam(lines[i].seg->x - view.x, lines[i].seg->y - view.y); + binangle endang = bvectangbam(wall[lines[i].seg->point2].x - view.x, wall[lines[i].seg->point2].y - view.y); if (endang.asbam() - startang.asbam() >= ANGLE_180) { @@ -573,14 +574,17 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe int newx = int((x << 1) + Scale(dx, i, j) - view.x); int newy = int((y << 1) + Scale(dy, i, j) - view.y); - int newan = ((gethiq16angle(dx, dy) << 1) - bamang(vp.RotAngle).asq16()) & 0x7FFFFFF; - vp.RotAngle = q16ang(newan).asbam(); + + auto myan = bvectangbam(dx, dy); + auto newan = myan + myan - bamang(vp.RotAngle); + + vp.RotAngle = newan.asbam(); vp.SectNums = nullptr; vp.SectCount = line->sector; vp.Pos.X = newx / 16.f; vp.Pos.Y = newy / -16.f; - vp.HWAngles.Yaw = -90.f + q16ang(newan).asdeg(); + vp.HWAngles.Yaw = -90.f + newan.asdeg(); double FocalTangent = tan(vp.FieldOfView.Radians() / 2); DAngle an = 270. - vp.HWAngles.Yaw.Degrees; @@ -597,9 +601,9 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(line->x - newx, line->y - newy); - auto endan = gethiq16angle(wall[line->point2].x - newx, wall[line->point2].y - newy); - clipper->SafeAddClipRange(q16ang(startan), q16ang(endan)); // we check the line from the backside so angles are reversed. + auto startan = bvectangbam(line->x - newx, line->y - newy); + auto endan = bvectangbam(wall[line->point2].x - newx, wall[line->point2].y - newy); + clipper->SafeAddClipRange(startan, endan); // we check the line from the backside so angles are reversed. return true; } @@ -646,10 +650,10 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl int dx2 = wall[line->point2].x - line->x; int dy2 = wall[line->point2].y - line->y; - int srcang = gethiq16angle(dx, dy); - int destang = gethiq16angle(-dx, -dy); + auto srcang = bvectangbam(dx, dy); + auto destang = bvectangbam(-dx, -dy); - vp.RotAngle += q16ang(destang - srcang).asbam(); + vp.RotAngle += (destang - srcang).asbam(); #endif // Nothing in the entire setup mandates that both lines have the same length. @@ -669,9 +673,9 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(origin->x - origx, origin->y - origy); - auto endan = gethiq16angle(wall[origin->point2].x - origx, wall[origin->point2].y - origy); - clipper->SafeAddClipRange(q16ang(endan), q16ang(startan)); + auto startan = bvectangbam(origin->x - origx, origin->y - origy); + auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); + clipper->SafeAddClipRange(endan, startan); return true; } @@ -723,9 +727,9 @@ bool HWLineToSpritePortal::Setup(HWDrawInfo* di, FRenderState& rstate, Clipper* angle_t af = di->FrustumAngle(); if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af)); - auto startan = gethiq16angle(origin->x - origx, origin->y - origy); - auto endan = gethiq16angle(wall[origin->point2].x - origx, wall[origin->point2].y - origy); - clipper->SafeAddClipRange(q16ang(endan), q16ang(startan)); + auto startan = bvectangbam(origin->x - origx, origin->y - origy); + auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); + clipper->SafeAddClipRange(endan, startan); return true; } diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index c5ba9a144..4577ed0b8 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -32,6 +32,7 @@ CVAR(Bool,gl_noskyboxes, false, 0) FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap); +FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum); //========================================================================== // @@ -42,14 +43,14 @@ FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilema void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane, PalEntry FadeColor) { int picnum = plane == plane_ceiling ? sector->ceilingpicnum : sector->floorpicnum; + int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal; int32_t dapyscale = 0, dapskybits = 0, dapyoffs = 0, daptileyscale = 0; - FGameTexture* skytex = nullptr; + FGameTexture* skytex = SkyboxReplacement(tileGetTexture(picnum)->GetID(), palette); int realskybits = 0; // todo: check for skybox replacement. if (!skytex) { - int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal; int remap = TRANSLATION(Translation_Remap + curbasepal, palette); int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale); @@ -179,12 +180,7 @@ void HWWall::SkyTop(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype * { if (bs->ceilingstat & CSTAT_SECTOR_SKY) { - float c1, c2, f1, f2; - PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); - PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); - - // if the back sector is closed the sky must be drawn! - if (c1 > f1 || c2 > f2) return; + return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! @@ -231,14 +227,10 @@ void HWWall::SkyBottom(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype } else if (fs->floorstat & CSTAT_SECTOR_SKY) { - float c1, c2, f1, f2; - PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); - PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); if (bs->floorstat & CSTAT_SECTOR_SKY) { - // if the back sector is closed the sky must be drawn! - if (c1 > f1 || c2 > f2) return; + return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! } diff --git a/source/core/rendering/scene/hw_skyportal.cpp b/source/core/rendering/scene/hw_skyportal.cpp index 22865de75..457b97fe1 100644 --- a/source/core/rendering/scene/hw_skyportal.cpp +++ b/source/core/rendering/scene/hw_skyportal.cpp @@ -26,7 +26,8 @@ #include "hw_renderstate.h" #include "skyboxtexture.h" - CVAR(Float, skyoffsettest, 0, 0) +CVAR(Float, skyoffsettest, 0, 0) + //----------------------------------------------------------------------------- // // @@ -34,6 +35,8 @@ //----------------------------------------------------------------------------- void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) { + int indexed = hw_int_useindexedcolortextures; + hw_int_useindexedcolortextures = false; // this code does not work with indexed textures. bool drawBoth = false; auto &vp = di->Viewpoint; @@ -101,6 +104,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) //di->lightmode = oldlightmode; state.SetDepthClamp(oldClamp); -} + hw_int_useindexedcolortextures = indexed; + } const char *HWSkyPortal::GetName() { return "Sky"; } diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 4fe85f31f..17934fac3 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -44,10 +44,7 @@ #include "hw_renderstate.h" #include "hw_models.h" #include "hw_viewpointbuffer.h" - -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - +#include "hw_voxels.h" //========================================================================== // @@ -74,7 +71,7 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture || !texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_Greater, 0.f); if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One) @@ -113,36 +110,15 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) } // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; // Disable brightmaps if non-black fog is used. int shade = this->shade; - PalEntry color(255, globalr, globalg, globalb); if (this->shade > numshades) // handling of SW's shadow hack using a shade of 127. { shade = sector[sprite->sectnum].floorshade; - color = 0xff000000; - } - shade = clamp(shade, 0, numshades - 1); - - if (ShadeDiv >= 1 / 1000.f && foggy && !foglayer) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); + state.SetColor(0, 0, 0, alpha); } - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(color, alpha); + SetLightAndFog(state, fade, palette, shade, visibility, alpha, this->shade <= numshades); if (modelframe == 0) { @@ -157,15 +133,20 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) state.SetLightIndex(-1); state.Draw(DT_TriangleStrip, vertexindex, 4); - if (ShadeDiv >= 1 / 1000.f && foggy && foglayer) + if (foglayer) { - // If we get here we know that we have colored fog and no fixed colormap. - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetTextureMode(TM_FOGLAYER); - state.SetRenderStyle(STYLE_Translucent); - state.Draw(DT_TriangleStrip, vertexindex, 4); - state.SetTextureMode(TM_NORMAL); + bool foggy = (GlobalMapFog || (fade & 0xffffff)); + auto ShadeDiv = lookups.tables[palette].ShadeFactor; + if (ShadeDiv >= 1 / 1000.f && foggy) + { + // If we get here we know that we have colored fog and no fixed colormap. + float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); + state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); + state.SetTextureMode(TM_FOGLAYER); + state.SetRenderStyle(STYLE_Translucent); + state.Draw(DT_TriangleStrip, vertexindex, 4); + state.SetTextureMode(TM_NORMAL); + } } } else @@ -352,17 +333,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int fade = lookups.getFade(sector->floorpal); // fog is per sector. visibility = sectorVisibility(sector); - bool trans = (spr->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(spr, alpha, RenderStyle); x = spr->x * (1 / 16.f); z = spr->z * (1 / -256.f); @@ -375,12 +346,12 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int int tilenum = spr->picnum; int xsize, ysize, tilexoff, tileyoff; - if (hw_hightile && TileFiles.tiledata[tilenum].h_xsize) + if (hw_hightile && TileFiles.tiledata[tilenum].hiofs.xsize) { - xsize = TileFiles.tiledata[tilenum].h_xsize; - ysize = TileFiles.tiledata[tilenum].h_ysize; - tilexoff = TileFiles.tiledata[tilenum].h_xoffs; - tileyoff = TileFiles.tiledata[tilenum].h_yoffs; + xsize = TileFiles.tiledata[tilenum].hiofs.xsize; + ysize = TileFiles.tiledata[tilenum].hiofs.ysize; + tilexoff = TileFiles.tiledata[tilenum].hiofs.xoffs; + tileyoff = TileFiles.tiledata[tilenum].hiofs.yoffs; } else { @@ -436,6 +407,12 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int z1 = z + yoff; z2 = z + height + yoff; + if (z1 < z2) + { + // Make sure that z1 is the higher one. Some utilities expect it to be oriented this way. + std::swap(z1, z2); + std::swap(vt, vb); + } } else { @@ -459,7 +436,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int } #endif - PutSprite(di, alpha < 1.f-FLT_EPSILON || modelframe == 0); + PutSprite(di, true); rendered_sprites++; } @@ -487,23 +464,13 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se if ((spr->cstat & CSTAT_SPRITE_MDLROTATE) || rotate) { int myclock = (PlayClock << 3) + MulScale(4 << 3, (int)di->Viewpoint.TicFrac, 16); - ang = (ang + myclock) & 2047; // will be applied in md3_vox_calcmat_common. + ang = (ang + myclock) & 2047; } if (!vox || (spr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_FLOOR) return false; - bool trans = (spr->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } + SetSpriteTranslucency(spr, alpha, RenderStyle); auto sprext = &spriteext[spr->owner]; @@ -568,7 +535,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se auto vp = di->Viewpoint; depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); - PutSprite(di, alpha < 1.f - FLT_EPSILON); + PutSprite(di, spriteHasTranslucency(sprite)); rendered_sprites++; return true; } diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index d21e7d911..b41ae6f2a 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -39,9 +39,6 @@ #include "flatvertices.h" #include "glbackend/glbackend.h" -extern PalEntry GlobalMapFog; -extern float GlobalFogDensity; - //========================================================================== // // Create vertices for one wall @@ -104,7 +101,7 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) if (gl_fogmode)// && !di->isFullbrightScene()) { state.EnableDrawBufferAttachments(false); - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); state.SetEffect(EFF_FOGBOUNDARY); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetDepthBias(-1, -128); @@ -115,38 +112,6 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) } } -//========================================================================== -// -// -// -//========================================================================== - -void HWWall::SetLightAndFog(FRenderState& state) -{ - // Fog must be done before the texture so that the texture selector can override it. - bool foggy = (GlobalMapFog || (fade & 0xffffff)); - auto ShadeDiv = lookups.tables[palette].ShadeFactor; - // Disable brightmaps if non-black fog is used. - if (ShadeDiv >= 1 / 1000.f && foggy) - { - state.EnableFog(1); - float density = GlobalMapFog ? GlobalFogDensity : 350.f - Scale(numshades - shade, 150, numshades); - state.SetFog((GlobalMapFog) ? GlobalMapFog : fade, density * hw_density); - state.SetSoftLightLevel(255); - state.SetLightParms(128.f, 1 / 1000.f); - } - else - { - state.EnableFog(0); - state.SetFog(0, 0); - state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(shade, 255, numshades) : 255); - state.SetLightParms(visibility, ShadeDiv / (numshades - 2)); - } - - // The shade rgb from the tint is ignored here. - state.SetColorAlpha(PalEntry(255, globalr, globalg, globalb), alpha); -} - //========================================================================== // // @@ -163,7 +128,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) // Use sphere mapping for this state.SetEffect(EFF_SPHEREMAP); - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha, false); state.SetColor(PalEntry(25, globalr >> 1, globalg >> 1, globalb >> 1)); state.SetRenderStyle(STYLE_Add); @@ -176,7 +141,7 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) state.EnableTextureMatrix(false); state.SetEffect(EFF_NONE); - state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); + state.AlphaFunc(Alpha_GEqual, 0.5f); state.SetDepthFunc(DF_Less); state.SetRenderStyle(STYLE_Translucent); @@ -190,11 +155,8 @@ void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) { - //int tmode = state.GetTextureMode(); - - state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr? (flags & (HWF_CLAMPX | HWF_CLAMPY)) : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); - - SetLightAndFog(state); + SetLightAndFog(state, fade, palette, shade, visibility, alpha); + state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr ? (flags & (HWF_CLAMPX | HWF_CLAMPY)) : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); int h = (int)texture->GetDisplayHeight(); int h2 = 1 << sizeToBits(h); @@ -238,7 +200,7 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state) state.SetRenderStyle(RenderStyle); state.SetTextureMode(RenderStyle); - if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + if (!texture || !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_GEqual, 0.f); RenderTexturedWall(di, state, HWWall::RWF_TEXTURED); state.SetRenderStyle(STYLE_Translucent); @@ -752,7 +714,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r tcs[UPRGT].v = setv(topleft, topright, glseg.fracright); tcs[LORGT].v = setv(bottomleft, bottomright, glseg.fracright); if (th == pow2size) CheckTexturePosition(); // for NPOT textures this adjustment can break things. - bool trans = type == RENDERWALL_M2S && (wal->cstat & CSTAT_WALL_TRANSLUCENT); + bool trans = type == RENDERWALL_M2S && maskWallHasTranslucency(wal); if (trans) { RenderStyle = GetRenderStyle(0, !!(wal->cstat & CSTAT_WALL_TRANS_FLIP)); @@ -896,7 +858,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec #ifdef _DEBUG - if (wal - wall == 843) + if (wal - wall == 788) { int a = 0; } @@ -993,11 +955,14 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec { float bch1a = bch1; float bch2a = bch2; - if (ffh1 > bch1 && ffh2 > bch2) + if (ffh1 > bch1 || ffh2 > bch2) { - // the back sector's floor obstructs part of this wall - bch2a = ffh2; - bch1a = ffh1; + // the back sector's floor obstructs part of this wall. Todo: Handle the portal case better. + if ((ffh1 > bch1 && ffh2 > bch2) || frontsector->portalflags == PORTAL_SECTOR_FLOOR) + { + bch2a = ffh2; + bch1a = ffh1; + } } if (bch1a < fch1 || bch2a < fch2) @@ -1028,11 +993,14 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec // lower texture if (!(frontsector->floorstat & backsector->floorstat & CSTAT_SECTOR_SKY)) { - if (fch1 < bfh1 && fch2 < bfh2) + if (fch1 < bfh1 || fch2 < bfh2) { - // the back sector's ceiling obstructs part of this wall. - bfh1 = fch1; - bfh2 = fch2; + // the back sector's ceiling obstructs part of this wall. Todo: Handle the portal case better. + if ((fch1 < bfh1 && fch2 < bfh2) || frontsector->portalflags == PORTAL_SECTOR_CEILING) + { + bfh1 = fch1; + bfh2 = fch2; + } } if (bfh1 > ffh1 || bfh2 > ffh2) @@ -1049,7 +1017,6 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec } } } - globalr = globalg = globalb = 255; } void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sector) @@ -1090,24 +1057,13 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect fade = lookups.getFade(sector->floorpal); // fog is per sector. visibility = sectorVisibility(sector); - bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT); - if (trans) - { - RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); - } - else - { - RenderStyle = LegacyRenderStyles[STYLE_Translucent]; - alpha = 1.f; - } - + SetSpriteTranslucency(sprite, alpha, RenderStyle); int height, topofs; - if (hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize) + if (hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) { - height = TileFiles.tiledata[spr->picnum].h_ysize; - topofs = (TileFiles.tiledata[spr->picnum].h_yoffs + spr->yoffset); + height = TileFiles.tiledata[spr->picnum].hiofs.ysize; + topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + spr->yoffset); } else { @@ -1160,5 +1116,5 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect zbottom[0] = zbottom[1] = floorz; } } - PutWall(di, trans); + PutWall(di, spriteHasTranslucency(sprite)); } \ No newline at end of file diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 030e9234a..74de2d8af 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -646,7 +646,6 @@ void SerializeMap(FSerializer& arc) ("numshades", numshades) // is this really needed? ("visibility", g_visibility) ("parallaxtype", parallaxtype) - ("parallaxvisibility", parallaxvisibility) ("parallaxyo", parallaxyoffs_override) ("parallaxys", parallaxyscale_override) ("pskybits", pskybits_override) diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 886ade1c1..943178a68 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -840,7 +840,7 @@ public: clock += now - lastTime; if (clock == 0) clock = 1; } - bool skiprequest = clock > 100'000'000 && inputState.CheckAllInput() && !processed; + bool skiprequest = clock > 100'000'000 && inputState.CheckAllInput() && !processed && job.job->fadestate != DScreenJob::fadeout; lastTime = now; if (screenfade < 1.f && !M_Active()) @@ -848,7 +848,8 @@ public: float ms = (clock / 1'000'000) / job.job->fadetime; screenfade = clamp(ms, 0.f, 1.f); twod->SetScreenFade(screenfade); - job.job->fadestate = DScreenJob::fadein; + if (job.job->fadestate != DScreenJob::fadeout) + job.job->fadestate = DScreenJob::fadein; } else { @@ -915,6 +916,7 @@ public: startTime = -1; clock = 0; jobs[index].job->fadestate = DScreenJob::fadeout; + gamestate = GS_INTRO; // block menu and console during fadeout - this can cause timing problems. actionState = State_Fadeout; } else @@ -959,6 +961,7 @@ void DeleteScreenJob() delete runner; runner = nullptr; } + twod->SetScreenFade(1); } void RunScreenJobFrame() diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index 95f5751b7..a515647d6 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -47,6 +47,7 @@ #include "c_dispatch.h" #include "sc_man.h" #include "gamestruct.h" +#include "hw_voxels.h" #include "hw_renderstate.h" @@ -59,7 +60,7 @@ enum BuildTiles TileFiles; -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags); +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor); //========================================================================== // @@ -144,7 +145,7 @@ void BuildTiles::Init() tile.RotTile = { -1,-1 }; tile.replacement = ReplacementType::Art; tile.alphaThreshold = 0.5; - tile.h_xsize = 0; + tile.hiofs = {}; } } @@ -256,7 +257,7 @@ void BuildTiles::InvalidateTile(int num) if ((unsigned) num < MAXTILES) { auto tex = tiledata[num].texture; - tex->GetTexture()->SystemTextures.Clean(); + tex->CleanHardwareData(); tiledata[num].rawCache.data.Clear(); } } @@ -513,7 +514,7 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu TexMan.AddGameTexture(tex); TileFiles.tiledata[tilenum].backup = TileFiles.tiledata[tilenum].texture = tex; if (istexture) - tileSetHightileReplacement(tilenum, 0, fn, (float)(255 - alphacut) * (1.f / 255.f), 1.0f, 1.0f, 1.0, 1.0, 0); + tileSetHightileReplacement(tilenum, 0, fn, (float)(255 - alphacut) * (1.f / 255.f), 1.0f, 1.0f, 1.0, 1.0); return 0; } @@ -648,7 +649,7 @@ void artSetupMapArt(const char* filename) void tileDelete(int tile) { TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.GameByIndex(0); - vox_undefine(tile); + tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile. md_undefinetile(tile); } diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index d4fb7181e..b9c3a29ec 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -257,6 +257,11 @@ struct RawCacheNode uint64_t lastUseTime; }; +struct TileOffs +{ + int xsize, ysize, xoffs, yoffs; +}; + struct TileDesc { FGameTexture* texture; // the currently active tile @@ -269,8 +274,7 @@ struct TileDesc float alphaThreshold; // Sprite offset hackery for hires replacements. This only gets used for sprites in the 3D view, nothing else. - uint16_t h_xsize, h_ysize; - int8_t h_xoffs, h_yoffs; + TileOffs hiofs; }; diff --git a/source/core/textures/hightile.cpp b/source/core/textures/hightile.cpp index f5d240233..36f8e6315 100644 --- a/source/core/textures/hightile.cpp +++ b/source/core/textures/hightile.cpp @@ -48,15 +48,17 @@ #include "sc_man.h" #include "gamestruct.h" #include "hw_renderstate.h" +#include "skyboxtexture.h" CVARD(Bool, hw_shadeinterpolate, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable shade interpolation") struct HightileReplacement { - FGameTexture* faces[6]; // only one gets used by a texture, the other 5 are for skyboxes only + FGameTexture* image; FVector2 scale; float alphacut, specpower, specfactor; - uint16_t palnum, flags; + uint16_t palnum; + bool issky; }; static TMap> tileReplacements; @@ -91,7 +93,7 @@ static void AddReplacement(int picnum, const HightileReplacement& replace) auto& Hightiles = tileReplacements[picnum]; for (auto& ht : Hightiles) { - if (replace.palnum == ht.palnum && (replace.faces[1] == nullptr) == (ht.faces[1] == nullptr)) + if (replace.palnum == ht.palnum && replace.issky == ht.issky) { ht = replace; return; @@ -125,7 +127,7 @@ static HightileReplacement* FindReplacement(FTextureID picnum, int palnum, bool { for (auto& rep : *Hightiles) { - if (rep.palnum == palnum && (rep.faces[1] != nullptr) == skybox) return &rep; + if (rep.palnum == palnum && rep.issky == skybox) return &rep; } if (!palnum || palnum >= MAXPALOOKUPS - RESERVEDPALS) break; palnum = 0; @@ -137,11 +139,19 @@ int checkTranslucentReplacement(FTextureID picnum, int pal) { FGameTexture* tex = nullptr; auto si = FindReplacement(picnum, pal, 0); - if (si && hw_hightile) tex = si->faces[0]; + if (si && hw_hightile) tex = si->image; if (!tex || tex->GetTexelWidth() == 0 || tex->GetTexelHeight() == 0) return false; return tex && tex->GetTranslucency(); } +FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum) +{ + auto hr = FindReplacement(picnum, palnum, true); + if (!hr) return nullptr; + return hr->image; +} + + //========================================================================== // // Processes data from .def files into the textures @@ -163,19 +173,19 @@ void PostLoadSetup() { if (rep.palnum == GLOWPAL) { - glowTex = rep.faces[0]; + glowTex = rep.image; } if (rep.palnum == NORMALPAL) { - normalTex = rep.faces[0]; + normalTex = rep.image; } if (rep.palnum == SPECULARPAL) { - specTex = rep.faces[0]; + specTex = rep.image; } if (rep.palnum == DETAILPAL) { - detailTex = rep.faces[0]; + detailTex = rep.image; scalex = rep.scale.X; scaley = rep.scale.Y; } @@ -185,10 +195,10 @@ void PostLoadSetup() { for (auto& rep : *Hightile) { - if (rep.faces[1]) continue; // do not muck around with skyboxes (yet) + if (rep.issky) continue; // do not muck around with skyboxes (yet) if (rep.palnum < NORMALPAL) { - auto tex = rep.faces[0]; + auto tex = rep.image; // Make a copy so that multiple appearances of the same texture with different layers can be handled. They will all refer to the same internal texture anyway. tex = MakeGameTexture(tex->GetTexture(), "", ETextureType::Any); if (glowTex) tex->SetGlowmap(glowTex->GetTexture()); @@ -196,7 +206,7 @@ void PostLoadSetup() if (normalTex) tex->SetNormalmap(normalTex->GetTexture()); if (specTex) tex->SetSpecularmap(specTex->GetTexture()); tex->SetDetailScale(scalex, scaley); - rep.faces[0] = tex; + rep.image = tex; } } } @@ -237,7 +247,7 @@ void PostLoadSetup() // //========================================================================== -int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, uint8_t flags) +int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor) { if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; @@ -257,13 +267,12 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo return -1; } - replace.faces[0] = TexMan.GetGameTexture(texid); - if (replace.faces[0] == nullptr) + replace.image = TexMan.GetGameTexture(texid); replace.alphacut = min(alphacut,1.f); replace.scale = { xscale, yscale }; replace.specpower = specpower; // currently unused replace.specfactor = specfactor; // currently unused - replace.flags = flags; + replace.issky = 0; replace.palnum = (uint16_t)palnum; AddReplacement(picnum, replace); return 0; @@ -276,10 +285,10 @@ int tileSetHightileReplacement(int picnum, int palnum, const char* filename, flo // //========================================================================== -int tileSetSkybox(int picnum, int palnum, const char **facenames, int flags ) +int tileSetSkybox(int picnum, int palnum, FString* facenames) { - if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; - if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; + if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1; + if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1; auto tex = tileGetTexture(picnum); if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) @@ -288,18 +297,25 @@ int tileSetSkybox(int picnum, int palnum, const char **facenames, int flags ) return -1; // cannot add replacements to empty tiles, must create one beforehand } HightileReplacement replace = {}; - - for (auto &face : replace.faces) + + FGameTexture *faces[6]; + for (int i = 0; i < 6; i++) { - FTextureID texid = TexMan.CheckForTexture(*facenames, ETextureType::Any); + FTextureID texid = TexMan.CheckForTexture(facenames[i], ETextureType::Any); if (!texid.isValid()) { - Printf("%s: Skybox image for tile %d does not exist or is invalid\n", *facenames, picnum); + Printf("%s: Skybox image for tile %d does not exist or is invalid\n", facenames[i].GetChars(), picnum); return -1; } - face = TexMan.GetGameTexture(texid); + faces[i] = TexMan.GetGameTexture(texid); } - replace.flags = flags; + FSkyBox* sbtex = new FSkyBox(""); + memcpy(sbtex->faces, faces, sizeof(faces)); + sbtex->previous = faces[0]; // won't ever be used, just to be safe. + sbtex->fliptop = true; + replace.image = MakeGameTexture(sbtex, "", ETextureType::Override); + TexMan.AddGameTexture(replace.image, false); + replace.issky = 1; replace.palnum = (uint16_t)palnum; AddReplacement(picnum, replace); return 0; @@ -341,7 +357,7 @@ bool PickTexture(FRenderState *state, FGameTexture* tex, int paletteid, TextureP if (rep) { - tex = rep->faces[0]; + tex = rep->image; } if (!rep || rep->palnum != hipalswap || (h.tintFlags & TINTF_APPLYOVERALTPAL)) applytint = true; diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp index 0f21c89e7..949052ceb 100644 --- a/source/games/blood/src/animatesprite.cpp +++ b/source/games/blood/src/animatesprite.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_2ddrawer.h" #include "v_video.h" #include "v_font.h" +#include "hw_voxels.h" #include "glbackend/glbackend.h" BEGIN_BLD_NS diff --git a/source/games/blood/src/barf.cpp b/source/games/blood/src/barf.cpp index f5f6f6381..ad218159c 100644 --- a/source/games/blood/src/barf.cpp +++ b/source/games/blood/src/barf.cpp @@ -656,7 +656,7 @@ void ParseScript(int lumpnum) if (dword_44CE0[gParseLevel] == 0) { // In the RFS files I have seen the outermost directory is not part of what goes into the file system. - auto inp1 = strchr(inp, '\\'); + auto inp1 = strpbrk(inp, "/\\"); if (!inp1 || !fileSystem.CreatePathlessCopy(inp1 + 1, ID, nFlags)) { // I'll activate this when I find evidence that it is needed. Otherwise the risk of picking up unwanted data is too high. diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 55399119e..f9ac09273 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -465,9 +465,6 @@ void GameInterface::app_init() HookReplaceFunctions(); - Printf(PRINT_NONOTIFY, "Initializing Build 3D engine\n"); - engineInit(); - Printf(PRINT_NONOTIFY, "Loading tiles\n"); if (!tileInit(0, NULL)) I_FatalError("TILES###.ART files not found"); diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index ad1cd6ad9..462fbe316 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -115,6 +115,28 @@ void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSectio static const char* DefFile(void) { + int found = -1; + if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0) + { + int numlumps = fileSystem.GetNumEntries(); + for (int i = numlumps - 1; i >= 0; i--) + { + if (fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) break; + FString fn = fileSystem.GetFileFullName(i, false); + FString ext = fn.Right(4); + if (ext.CompareNoCase(".ini") == 0) + { + if (fileSystem.CheckNumForFullName(fn) != i) continue; + if (found == -1) found = i; + else + { + found = -1; + break; + } + } + } + } + if (found >= 0) return fileSystem.GetFileFullName(found); // The command line parser stores this in the CON field. return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini"; } diff --git a/source/games/blood/src/misc.h b/source/games/blood/src/misc.h index cea185bf6..33d2d7704 100644 --- a/source/games/blood/src/misc.h +++ b/source/games/blood/src/misc.h @@ -122,7 +122,6 @@ extern short voxelIndex[MAXTILES]; extern int nPrecacheCount; int tileInit(char a1, const char *a2); -void tileProcessGLVoxels(void); void tilePreloadTile(int nTile); void tilePrecacheTile(int nTile, int nType, HitList& hits); diff --git a/source/games/blood/src/tile.cpp b/source/games/blood/src/tile.cpp index ac46809d1..3d81013e0 100644 --- a/source/games/blood/src/tile.cpp +++ b/source/games/blood/src/tile.cpp @@ -44,14 +44,11 @@ char surfType[kMaxTiles]; signed char tileShade[kMaxTiles]; short voxelIndex[kMaxTiles]; -const char *pzBaseFileName = "TILES%03i.ART"; //"TILES%03i.ART"; - int tileInit(char a1, const char *a2) { UNREFERENCED_PARAMETER(a1); if (artLoaded) return 1; - TileFiles.artLoadFiles(a2 ? a2 : pzBaseFileName); for (int i = 0; i < kMaxTiles; i++) voxelIndex[i] = 0; @@ -81,32 +78,9 @@ int tileInit(char a1, const char *a2) } artLoaded = 1; - - #ifdef USE_OPENGL - PolymostProcessVoxels_Callback = tileProcessGLVoxels; - #endif - return 1; } -#ifdef USE_OPENGL -void tileProcessGLVoxels(void) -{ - static bool voxInit = false; - if (voxInit) - return; - voxInit = true; - for (int i = 0; i < kMaxVoxels; i++) - { - auto index = fileSystem.FindResource(i, "KVX"); - if (index >= 0) - { - voxmodels[i] = voxload(index); - } - } -} -#endif - char tileGetSurfType(int hit) { int n = hit & 0x3fff; diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 3dd797e90..130074dd5 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -266,7 +266,7 @@ void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum if (pPlayer->weaponTimer == 0) // playing idle QAV? { // Double shotgun fix from BloodGDX. - if (/*!IsOriginalDemo() &&*/ (pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7)) && isOriginalQAV()) + if (/*!IsOriginalDemo() &&*/ (pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7))/* && isOriginalQAV()*/) duration = pQAV->duration - 1; else duration = (PlayClock + MulScale(4, smoothratio, 16)) % pQAV->duration; } diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 04d9e311e..ccce5da8c 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -4505,7 +4505,7 @@ void handle_se27(DDukeActor* actor) // //--------------------------------------------------------------------------- -void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, int TRIPBOMB, int LASERLINE, int CRANE, int shift) +void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, bool scroll, int TRIPBOMB, int LASERLINE, int CRANE, int shift) { int* t = &actor->temp_data[0]; @@ -4575,7 +4575,7 @@ void handle_se24(DDukeActor *actor, int16_t *list1, int16_t *list2, int TRIPBOMB } } } - sector[actor->s.sectnum].addfloorxpan(actor->s.yvel / 128.f); + if (scroll) sector[actor->s.sectnum].addfloorxpan(actor->s.yvel / 128.f); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 3ceaf8ed2..308866bd8 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -3697,7 +3697,7 @@ void moveeffectors_d(void) //STATNUM 3 { static int16_t list1[] = { BLOODPOOL, PUKE, FOOTPRINTS, FOOTPRINTS2, FOOTPRINTS3, FOOTPRINTS4, BULLETHOLE, BLOODSPLAT1, BLOODSPLAT2, BLOODSPLAT3, BLOODSPLAT4, -1 }; static int16_t list2[] = { BOLT1, BOLT1 + 1,BOLT1 + 2, BOLT1 + 3, SIDEBOLT1, SIDEBOLT1 + 1, SIDEBOLT1 + 2, SIDEBOLT1 + 3, -1 }; - handle_se24(act, list1, list2, TRIPBOMB, LASERLINE, CRANE, 2); + handle_se24(act, list1, list2, false, TRIPBOMB, LASERLINE, CRANE, 2); break; } case SE_35: diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index a6935be5a..f4988af0d 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -3576,7 +3576,7 @@ void moveeffectors_r(void) //STATNUM 3 { static int16_t list1[] = { BLOODPOOL, PUKE, FOOTPRINTS, FOOTPRINTS2, FOOTPRINTS3, -1 }; static int16_t list2[] = { BOLT1, BOLT1 + 1,BOLT1 + 2, BOLT1 + 3, -1 }; - handle_se24(act, list1, list2, BULLETHOLE, -1, CRANE, 1); + handle_se24(act, list1, list2, st != 156, BULLETHOLE, -1, CRANE, 1); break; } diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 29a56af54..1785fabce 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -84,7 +84,7 @@ void handle_se19(DDukeActor* i, int BIGFORCE); void handle_se20(DDukeActor* i); void handle_se21(DDukeActor* i); void handle_se22(DDukeActor* i); -void handle_se24(DDukeActor* actor, int16_t* list1, int16_t* list2, int TRIPBOMB, int LASERLINE, int CRANE, int shift); +void handle_se24(DDukeActor* actor, int16_t* list1, int16_t* list2, bool scroll, int TRIPBOMB, int LASERLINE, int CRANE, int shift); void handle_se25(DDukeActor* a, int t_index, int snd1, int snd2); void handle_se26(DDukeActor* i); void handle_se27(DDukeActor* i); diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index 181997346..8325fd7da 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -230,9 +230,6 @@ static void setupbackdrop() static void initTiles() { - if (TileFiles.artLoadFiles("tiles%03i.art") < 0) - I_FatalError("Failed loading art."); - tileDelete(TILE_MIRROR); skiptile = TILE_W_FORCEFIELD + 1; @@ -310,9 +307,6 @@ void GameInterface::app_init() OnEvent(EVENT_INIT); - if (engineInit()) - G_FatalEngineError(); - //Net_SendClientInfo(); initTiles(); diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index 79970b348..aefc53400 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -65,7 +65,6 @@ inline DDukeActor* getSndActor(const void* source) return source ? &hittype[((spritetype*)source) - sprite] : nullptr; } -TArray specialmusic; static FSoundID currentCommentarySound; static DDukeActor* currentCommentarySprite; // todo: GC this once actors become objects diff --git a/source/games/duke/src/sounds.h b/source/games/duke/src/sounds.h index 883496606..415af4406 100644 --- a/source/games/duke/src/sounds.h +++ b/source/games/duke/src/sounds.h @@ -74,8 +74,6 @@ void S_ParseDeveloperCommentary(); void StopCommentary(); bool StartCommentary(int tag, DDukeActor* sprnum); -extern TArray specialmusic; - END_DUKE_NS diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index 1a85073a5..11f64ca7d 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -785,7 +785,8 @@ void spawneffector(DDukeActor* actor) break; } case 156: - if (!isRRRA()) break; + break; + case 34: StartInterpolation(sect, Interp_Sect_FloorPanX); break; diff --git a/source/games/exhumed/src/exhumed.cpp b/source/games/exhumed/src/exhumed.cpp index 462c2923f..b2988a45d 100644 --- a/source/games/exhumed/src/exhumed.cpp +++ b/source/games/exhumed/src/exhumed.cpp @@ -75,12 +75,6 @@ void ResetEngine() void InstallEngine() { - TileFiles.LoadArtSet("tiles%03d.art"); - - if (engineInit()) - { - G_FatalEngineError(); - } uploadCinemaPalettes(); LoadPaletteLookups(); } diff --git a/source/games/exhumed/src/gameloop.cpp b/source/games/exhumed/src/gameloop.cpp index 4307b1325..949670c75 100644 --- a/source/games/exhumed/src/gameloop.cpp +++ b/source/games/exhumed/src/gameloop.cpp @@ -193,7 +193,7 @@ static void Intermission(MapRecord *from_map, MapRecord *to_map) gameaction = ga_nextlevel; } - }); + }, true, true); } } diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index e100ee4a5..1b8e8b2e0 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -1123,7 +1123,7 @@ void CameraView(PLAYERp pp, int *tx, int *ty, int *tz, short *tsectnum, binangle { sp = &sprite[i]; - ang = q16ang(gethiq16angle(*tx - sp->x, *ty - sp->y)); + ang = bvectangbam(*tx - sp->x, *ty - sp->y); ang_test = getincangle(ang.asbuild(), sp->ang) < sp->lotag; FAFcansee_test = @@ -1568,7 +1568,7 @@ drawscreen(PLAYERp pp, double smoothratio) if (TEST_BOOL1(pp->remote_sprite)) tang = buildang(pp->remote_sprite->ang); else - tang = q16ang(gethiq16angle(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty)); + tang = bvectangbam(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty); } if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE)) diff --git a/source/games/sw/src/game.cpp b/source/games/sw/src/game.cpp index 0f3a6c9cf..0c7ca198d 100644 --- a/source/games/sw/src/game.cpp +++ b/source/games/sw/src/game.cpp @@ -199,7 +199,6 @@ void GameInterface::app_init() registerosdcommands(); - engineInit(); auto pal = fileSystem.LoadFile("3drealms.pal", 0); if (pal.Size() >= 768) { @@ -220,8 +219,6 @@ void GameInterface::app_init() "the full version. Read the Ordering Info screens for details."); } - TileFiles.LoadArtSet("tiles%03d.art"); - //Connect(); SortBreakInfo(); parallaxtype = 1; diff --git a/source/games/sw/src/interpso.cpp b/source/games/sw/src/interpso.cpp index 48c211376..1f53b9de6 100644 --- a/source/games/sw/src/interpso.cpp +++ b/source/games/sw/src/interpso.cpp @@ -110,8 +110,10 @@ static void so_setpointinterpolation(so_interp *interp, int element) return; for (i = 0; i < interp->numinterpolations; i++) + { if (interp->data[i].curelement == element) return; + } so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; @@ -129,7 +131,7 @@ static void so_setspriteanginterpolation(so_interp *interp, int32_t spritenum) return; for (i = 0; i < interp->numinterpolations; i++) - if (interp->data[i].curelement == -1) + if (interp->data[i].curelement == -1 && interp->data[i].spriteofang == spritenum) return; so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; @@ -148,9 +150,16 @@ static void so_stopdatainterpolation(so_interp *interp, int element) int32_t i; for (i = 0; i < interp->numinterpolations; i++) - if (interp->data[i].curelement == element) + { + if (interp->data[i].curelement == -1) + { + if (interp->data[i].spriteofang == element) break; + } + else if (interp->data[i].curelement == element) break; + } + if (i == interp->numinterpolations) return; @@ -219,7 +228,7 @@ void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) so_setpointinterpolation(interp, snum | soi_spry); if (!interp->hasvator) so_setpointinterpolation(interp, snum | soi_sprz); - so_setspriteanginterpolation(interp, int(sp - sprite)); + so_setspriteanginterpolation(interp, snum); } void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) diff --git a/source/games/sw/src/player.cpp b/source/games/sw/src/player.cpp index 351df2422..a8ab12403 100644 --- a/source/games/sw/src/player.cpp +++ b/source/games/sw/src/player.cpp @@ -5471,7 +5471,7 @@ DoPlayerStopOperate(PLAYERp pp) if (TEST_BOOL1(pp->remote_sprite)) pp->angle.ang = pp->angle.oang = buildang(pp->remote_sprite->ang); else - pp->angle.ang = pp->angle.oang = q16ang(gethiq16angle(pp->sop_remote->xmid - pp->posx, pp->sop_remote->ymid - pp->posy)); + pp->angle.ang = pp->angle.oang = bvectangbam(pp->sop_remote->xmid - pp->posx, pp->sop_remote->ymid - pp->posy); } if (pp->sop_control) @@ -7148,7 +7148,9 @@ domovethings(void) // auto tracking mode for single player multi-game if (numplayers <= 1 && PlayerTrackingMode && pnum == screenpeek && screenpeek != myconnectindex) { - Player[screenpeek].angle.settarget(bvectangf(Player[myconnectindex].posx - Player[screenpeek].posx, Player[myconnectindex].posy - Player[screenpeek].posy)); + int deltax = Player[myconnectindex].posx - Player[screenpeek].posx; + int deltay = Player[myconnectindex].posy - Player[screenpeek].posy; + Player[screenpeek].angle.settarget(bvectangbam(deltax, deltay)); } if (!TEST(pp->Flags, PF_DEAD)) diff --git a/source/games/sw/src/sbar.cpp b/source/games/sw/src/sbar.cpp index c9cd50ba8..51a380646 100644 --- a/source/games/sw/src/sbar.cpp +++ b/source/games/sw/src/sbar.cpp @@ -695,7 +695,7 @@ private: void DisplayMinibarInventory(PLAYERp pp) { int InventoryBoxX = MINI_BAR_INVENTORY_BOX_X; - int InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y; + int InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y - 200; int InventoryXoff = 0; int InventoryYoff = 1; diff --git a/source/games/sw/src/scrip2.cpp b/source/games/sw/src/scrip2.cpp index d008ea556..ac36e7607 100644 --- a/source/games/sw/src/scrip2.cpp +++ b/source/games/sw/src/scrip2.cpp @@ -40,6 +40,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "razemenu.h" #include "quotemgr.h" #include "mapinfo.h" +#include "hw_voxels.h" BEGIN_SW_NS @@ -231,7 +232,7 @@ void LoadKVXFromScript(const char* filename) GetToken(false); // Load the voxel file into memory - if (!qloadkvx(lNumber,token)) + if (!voxDefine(lNumber,token)) { // Store the sprite and voxel numbers for later use aVoxelArray[lTile].Voxel = lNumber; // Voxel num diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 023c9475d..783e02d83 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -86,20 +86,3 @@ bool GLInstance::SetTexture(FGameTexture* tex, int paletteid, int sampler, bool return true; } -//=========================================================================== -// -// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker -// -//=========================================================================== - -void InitBuildTiles() -{ - -} - -TArray usershaders; - -void UpdateVRModes(bool considerQuadBuffered = true) -{ - // should update the menu. -} diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index dc44c5e37..a31f8aa70 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -70,33 +70,16 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state); GLInstance GLInterface; GLInstance::GLInstance() - :palmanager(this) { VSMatrix mat(0); matrixArray.Push(mat); } -IHardwareTexture *setpalettelayer(int layer, int translation) -{ - if (layer == 1) - return GLInterface.palmanager.GetPalette(GetTranslationType(translation) - Translation_Remap); - else if (layer == 2) - return GLInterface.palmanager.GetLookup(GetTranslationIndex(translation)); - else return nullptr; -} - void GLInstance::Init(int ydim) { - FMaterial::SetLayerCallback(setpalettelayer); new(&renderState) PolymostRenderState; // reset to defaults. } -void GLInstance::Deinit() -{ - palmanager.DeleteAll(); - lastPalswapIndex = -1; -} - void GLInstance::Draw(EDrawType type, size_t start, size_t count) { assert (BufferLock > 0); diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index a21ccb2a3..90512258d 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -21,25 +21,6 @@ class F2DDrawer; struct palette_t; extern int xdim, ydim; -class PaletteManager -{ - IHardwareTexture* palettetextures[256] = {}; - IHardwareTexture* lookuptextures[256] = {}; - - GLInstance* const inst; - - unsigned FindPalswap(const uint8_t* paldata, palette_t& fadecolor); - -public: - PaletteManager(GLInstance *inst_) : inst(inst_) - {} - ~PaletteManager(); - void DeleteAll(); - IHardwareTexture *GetPalette(int index); - IHardwareTexture* GetLookup(int index); -}; - - struct glinfo_t { float maxanisotropy; }; @@ -75,9 +56,7 @@ class GLInstance friend IHardwareTexture* setpalettelayer(int layer, int translation); public: - TArray rendercommands; - PaletteManager palmanager; - int lastPalswapIndex = -1; + TArray rendercommands; FGameTexture* currentTexture = nullptr; int MatrixChange = 0; @@ -90,8 +69,6 @@ public: void Init(int y); - void Deinit(); - static int GetTexDimension(int value) { //if (value > gl.max_texturesize) return gl.max_texturesize; diff --git a/wadsrc/static/filter/blood/engine/origbinds.txt b/wadsrc/static/filter/blood/engine/origbinds.txt index 85f93e3dc..e13f235d1 100644 --- a/wadsrc/static/filter/blood/engine/origbinds.txt +++ b/wadsrc/static/filter/blood/engine/origbinds.txt @@ -8,3 +8,8 @@ X "+Alt_Fire" J "useitem 4" M "useitem 1" Mouse2 "+Alt_Fire" + +unbind KP0 +unbind KP. +unbind DEL +unbind INS diff --git a/wadsrc/static/filter/exhumed/engine/engine.def b/wadsrc/static/filter/exhumed/engine/engine.def deleted file mode 100644 index eaa696b26..000000000 --- a/wadsrc/static/filter/exhumed/engine/engine.def +++ /dev/null @@ -1 +0,0 @@ -tilefromtexture 3463 { file "tiles/options.png" } \ No newline at end of file diff --git a/wadsrc/static/filter/exhumed/tiles/options.png b/wadsrc/static/filter/exhumed/tiles/options.png deleted file mode 100644 index a035cbae2..000000000 Binary files a/wadsrc/static/filter/exhumed/tiles/options.png and /dev/null differ diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index a9e6d5607..6b483eea1 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1617,13 +1617,20 @@ OptionValue GPUSwitch 2.0, "$OPTVAL_INTEGRATED" } +OptionValue PreferBackend +{ + 0, "$OPTVAL_OPENGL" + 1, "$OPTVAL_VULKAN" + // Enable when HAVE_SOFTPOLY will be defined + //2, "$OPTVAL_SOFTPOLY" +} + OptionMenu VideoModeMenu protected { Title "$VIDMNU_TITLE" - // does not work yet. - //Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" - //StaticText " " + Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" + StaticText " " Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" IfOption(Mac)