Merge branch 'brightmap-conversion' into 'master'

Convert BRIGHTMAP texture columns to match associated texture

See merge request KartKrew/Kart!1473
This commit is contained in:
Oni 2023-09-10 19:50:25 +00:00
commit 87d7cae5d3
8 changed files with 351 additions and 57 deletions

View file

@ -551,6 +551,7 @@ void D_RegisterClientCommands(void)
COM_AddDebugCommand("goto", Command_Goto_f); COM_AddDebugCommand("goto", Command_Goto_f);
COM_AddDebugCommand("angle", Command_Angle_f); COM_AddDebugCommand("angle", Command_Angle_f);
COM_AddDebugCommand("respawnat", Command_RespawnAt_f); COM_AddDebugCommand("respawnat", Command_RespawnAt_f);
COM_AddDebugCommand("goto_skybox", Command_GotoSkybox_f);
{ {
extern struct CVarList *cvlist_player; extern struct CVarList *cvlist_player;

View file

@ -640,6 +640,23 @@ void Command_RespawnAt_f(void)
D_Cheat(consoleplayer, CHEAT_RESPAWNAT, atoi(COM_Argv(1))); D_Cheat(consoleplayer, CHEAT_RESPAWNAT, atoi(COM_Argv(1)));
} }
void Command_GotoSkybox_f(void)
{
REQUIRE_CHEATS;
REQUIRE_INLEVEL;
mobj_t *skybox = players[consoleplayer].skybox.viewpoint;
if (P_MobjWasRemoved(skybox))
{
CONS_Printf("There is no visible skybox for local Player 1.\n");
return;
}
D_Cheat(consoleplayer, CHEAT_TELEPORT, skybox->x, skybox->y, skybox->z);
D_Cheat(consoleplayer, CHEAT_ANGLE, skybox->angle);
}
// //
// OBJECTPLACE (and related variables) // OBJECTPLACE (and related variables)
// //

View file

@ -91,6 +91,7 @@ void Command_Grayscale_f(void);
void Command_Goto_f(void); void Command_Goto_f(void);
void Command_Angle_f(void); void Command_Angle_f(void);
void Command_RespawnAt_f(void); void Command_RespawnAt_f(void);
void Command_GotoSkybox_f(void);
#ifdef _DEBUG #ifdef _DEBUG
void Command_CauseCfail_f(void); void Command_CauseCfail_f(void);
#endif #endif

View file

@ -1029,6 +1029,9 @@ void R_DrawSinglePlane(visplane_t *pl)
INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num); INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num);
if (bmNum != 0) if (bmNum != 0)
{ {
// FIXME: This has the potential to read out of
// bounds if the brightmap texture is not as
// large as the flat.
ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum); ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum);
} }
} }

View file

@ -40,7 +40,7 @@ static boolean markceiling;
static boolean maskedtexture; static boolean maskedtexture;
static INT32 toptexture, bottomtexture, midtexture; static INT32 toptexture, bottomtexture, midtexture;
static INT32 topbrightmap, bottombrightmap, midbrightmap; static bool topbrightmapped, bottombrightmapped, midbrightmapped;
static INT32 numthicksides, numbackffloors; static INT32 numthicksides, numbackffloors;
angle_t rw_normalangle; angle_t rw_normalangle;
@ -160,7 +160,7 @@ static inline boolean R_OverflowTest(void)
return false; return false;
} }
static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnum, INT32 bmnum, void (*colfunc_2s)(column_t *, column_t *, INT32)) static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnum, void (*colfunc_2s)(column_t *, column_t *, INT32))
{ {
size_t pindex; size_t pindex;
column_t *col, *bmCol = NULL; column_t *col, *bmCol = NULL;
@ -173,6 +173,7 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu
sector_t *front, *back; sector_t *front, *back;
INT32 times, repeats; INT32 times, repeats;
boolean tripwire; boolean tripwire;
boolean brightmapped = R_TextureHasBrightmap(texnum);
ldef = curline->linedef; ldef = curline->linedef;
tripwire = P_IsLineTripWire(ldef); tripwire = P_IsLineTripWire(ldef);
@ -350,7 +351,11 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu
// draw the texture // draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
if (brightmapped)
{
bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3);
}
for (i = 0; i < dc_numlights; i++) for (i = 0; i < dc_numlights; i++)
{ {
@ -449,7 +454,11 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu
// draw the texture // draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
if (brightmapped)
{
bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3);
}
#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
@ -557,7 +566,7 @@ static INT32 R_GetTwoSidedMidTexture(seg_t *line)
return R_GetTextureNum(texture); return R_GetTextureNum(texture);
} }
static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum) static boolean R_CheckBlendMode(const line_t *ldef, boolean brightmapped)
{ {
transnum_t transtable = NUMTRANSMAPS; transnum_t transtable = NUMTRANSMAPS;
patchalphastyle_t blendmode = AST_COPY; patchalphastyle_t blendmode = AST_COPY;
@ -578,18 +587,18 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum)
if (blendmode == AST_FOG) if (blendmode == AST_FOG)
{ {
R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); R_SetColumnFunc(COLDRAWFUNC_FOG, brightmapped);
windowtop = frontsector->ceilingheight; windowtop = frontsector->ceilingheight;
windowbottom = frontsector->floorheight; windowbottom = frontsector->floorheight;
} }
else if (transtable != NUMTRANSMAPS && (blendmode || transtable)) else if (transtable != NUMTRANSMAPS && (blendmode || transtable))
{ {
dc_transmap = R_GetBlendTable(blendmode, transtable); dc_transmap = R_GetBlendTable(blendmode, transtable);
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped);
} }
else else
{ {
R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); R_SetColumnFunc(BASEDRAWFUNC, brightmapped);
} }
if (curline->polyseg && curline->polyseg->translucency > 0) if (curline->polyseg && curline->polyseg->translucency > 0)
@ -598,7 +607,7 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum)
return false; return false;
dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency); dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency);
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped);
} }
return true; return true;
@ -606,7 +615,7 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum)
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
INT32 texnum, bmnum; INT32 texnum;
void (*colfunc_2s)(column_t *, column_t *, INT32); void (*colfunc_2s)(column_t *, column_t *, INT32);
line_t *ldef; line_t *ldef;
const boolean debug = R_IsDebugLine(ds->curline); const boolean debug = R_IsDebugLine(ds->curline);
@ -620,14 +629,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
frontsector = curline->frontsector; frontsector = curline->frontsector;
backsector = curline->backsector; backsector = curline->backsector;
texnum = R_GetTwoSidedMidTexture(curline); texnum = R_GetTwoSidedMidTexture(curline);
bmnum = R_GetTextureBrightmap(texnum);
windowbottom = windowtop = sprbotscreen = INT32_MAX; windowbottom = windowtop = sprbotscreen = INT32_MAX;
ldef = curline->linedef; ldef = curline->linedef;
R_CheckDebugHighlight(SW_HI_MIDTEXTURES); R_CheckDebugHighlight(SW_HI_MIDTEXTURES);
if (debug == false && R_CheckBlendMode(ldef, bmnum) == false) if (debug == false && R_CheckBlendMode(ldef, R_TextureHasBrightmap(texnum)) == false)
{ {
return; // does not render return; // does not render
} }
@ -638,7 +646,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// Texture must be cached before setting colfunc_2s, // Texture must be cached before setting colfunc_2s,
// otherwise texture[texnum]->holes may be false when it shouldn't be // otherwise texture[texnum]->holes may be false when it shouldn't be
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
if (bmnum) { R_CheckTextureCache(bmnum); }
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2 // are not stored per-column with post info in SRB2
@ -671,7 +678,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
else else
{ {
R_RenderMaskedSegLoop(ds, x1, x2, texnum, bmnum, colfunc_2s); R_RenderMaskedSegLoop(ds, x1, x2, texnum, colfunc_2s);
} }
R_SetColumnFunc(BASEDRAWFUNC, false); R_SetColumnFunc(BASEDRAWFUNC, false);
@ -719,7 +726,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
size_t pindex = 0; size_t pindex = 0;
column_t * col, *bmCol = NULL; column_t * col, *bmCol = NULL;
INT32 lightnum; INT32 lightnum;
INT32 texnum, bmnum; INT32 texnum;
sector_t tempsec; sector_t tempsec;
INT32 templight; INT32 templight;
INT32 i, p; INT32 i, p;
@ -751,20 +758,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
backsector = pfloor->target; backsector = pfloor->target;
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
bmnum = R_GetTextureBrightmap(texnum);
R_CheckDebugHighlight(SW_HI_FOFSIDES); R_CheckDebugHighlight(SW_HI_FOFSIDES);
R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0);
if (pfloor->master->flags & ML_TFERLINE) if (pfloor->master->flags & ML_TFERLINE)
{ {
size_t linenum = curline->linedef-backsector->lines[0]; size_t linenum = curline->linedef-backsector->lines[0];
newline = pfloor->master->frontsector->lines[0] + linenum; newline = pfloor->master->frontsector->lines[0] + linenum;
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
bmnum = R_GetTextureBrightmap(texnum);
} }
boolean brightmapped = R_TextureHasBrightmap(texnum);
R_SetColumnFunc(BASEDRAWFUNC, brightmapped);
if (pfloor->fofflags & FOF_TRANSLUCENT) if (pfloor->fofflags & FOF_TRANSLUCENT)
{ {
boolean fuzzy = true; boolean fuzzy = true;
@ -781,12 +788,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (fuzzy) if (fuzzy)
{ {
R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped);
} }
} }
else if (pfloor->fofflags & FOF_FOG) else if (pfloor->fofflags & FOF_FOG)
{ {
R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); R_SetColumnFunc(COLDRAWFUNC_FOG, brightmapped);
} }
range = std::max(ds->x2-ds->x1, 1); range = std::max(ds->x2-ds->x1, 1);
@ -980,7 +987,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Texture must be cached before setting colfunc_2s, // Texture must be cached before setting colfunc_2s,
// otherwise texture[texnum]->holes may be false when it shouldn't be // otherwise texture[texnum]->holes may be false when it shouldn't be
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
if (bmnum) { R_CheckTextureCache(bmnum); }
//faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info anymore in Doom Legacy // are not stored per-column with post info anymore in Doom Legacy
@ -1065,7 +1071,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Get data for the column // Get data for the column
col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); }
if (brightmapped)
{
bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3);
}
// SoM: New code does not rely on R_DrawColumnShadowed_8 which // SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack. // will (hopefully) put less strain on the stack.
@ -1276,13 +1286,13 @@ UINT32 nombre = 100000;
#endif #endif
//profile stuff --------------------------------------------------------- //profile stuff ---------------------------------------------------------
static void R_DrawWallColumn(INT32 yl, INT32 yh, fixed_t mid, fixed_t texturecolumn, INT32 texture, INT32 brightmap) static void R_DrawWallColumn(INT32 yl, INT32 yh, fixed_t mid, fixed_t texturecolumn, INT32 texture, boolean brightmapped)
{ {
dc_yl = yl; dc_yl = yl;
dc_yh = yh; dc_yh = yh;
dc_texturemid = mid; dc_texturemid = mid;
dc_source = R_GetColumn(texture, texturecolumn); dc_source = R_GetColumn(texture, texturecolumn);
dc_brightmap = (brightmap ? R_GetColumn(brightmap, texturecolumn) : NULL); dc_brightmap = (brightmapped ? R_GetBrightmapColumn(texture, texturecolumn) : NULL);
dc_texheight = textureheight[texture] >> FRACBITS; dc_texheight = textureheight[texture] >> FRACBITS;
R_SetColumnFunc(colfunctype, dc_brightmap != NULL); R_SetColumnFunc(colfunctype, dc_brightmap != NULL);
colfunc(); colfunc();
@ -1560,7 +1570,7 @@ static void R_RenderSegLoop (void)
// single sided line // single sided line
if (yl <= yh && yh >= 0 && yl < viewheight) if (yl <= yh && yh >= 0 && yl < viewheight)
{ {
R_DrawWallColumn(yl, yh, rw_midtexturemid, texturecolumn, midtexture, midbrightmap); R_DrawWallColumn(yl, yh, rw_midtexturemid, texturecolumn, midtexture, midbrightmapped);
// dont draw anything more for this column, since // dont draw anything more for this column, since
// a midtexture blocks the view // a midtexture blocks the view
@ -1599,7 +1609,7 @@ static void R_RenderSegLoop (void)
} }
else if (mid >= 0) // safe to draw top texture else if (mid >= 0) // safe to draw top texture
{ {
R_DrawWallColumn(yl, mid, rw_toptexturemid, texturecolumn, toptexture, topbrightmap); R_DrawWallColumn(yl, mid, rw_toptexturemid, texturecolumn, toptexture, topbrightmapped);
ceilingclip[rw_x] = (INT16)mid; ceilingclip[rw_x] = (INT16)mid;
} }
else if (!rw_ceilingmarked) // entirely off top of screen else if (!rw_ceilingmarked) // entirely off top of screen
@ -1630,7 +1640,7 @@ static void R_RenderSegLoop (void)
} }
else if (mid < viewheight) // safe to draw bottom texture else if (mid < viewheight) // safe to draw bottom texture
{ {
R_DrawWallColumn(mid, yh, rw_bottomtexturemid, texturecolumn, bottomtexture, bottombrightmap); R_DrawWallColumn(mid, yh, rw_bottomtexturemid, texturecolumn, bottomtexture, bottombrightmapped);
floorclip[rw_x] = (INT16)mid; floorclip[rw_x] = (INT16)mid;
} }
else if (!rw_floormarked) // entirely off bottom of screen else if (!rw_floormarked) // entirely off bottom of screen
@ -1914,7 +1924,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
worldbottomslope -= viewz; worldbottomslope -= viewz;
midtexture = toptexture = bottomtexture = maskedtexture = 0; midtexture = toptexture = bottomtexture = maskedtexture = 0;
midbrightmap = topbrightmap = bottombrightmap = 0; midbrightmapped = topbrightmapped = bottombrightmapped = false;
ds_p->maskedtexturecol = NULL; ds_p->maskedtexturecol = NULL;
ds_p->numthicksides = numthicksides = 0; ds_p->numthicksides = numthicksides = 0;
ds_p->thicksidecol = NULL; ds_p->thicksidecol = NULL;
@ -1962,7 +1972,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
fixed_t texheight; fixed_t texheight;
// single sided line // single sided line
midtexture = R_GetTextureNum(sidedef->midtexture); midtexture = R_GetTextureNum(sidedef->midtexture);
midbrightmap = R_GetTextureBrightmap(midtexture); midbrightmapped = R_TextureHasBrightmap(midtexture);
texheight = textureheight[midtexture]; texheight = textureheight[midtexture];
// a single sided line is terminal, so it must mark ends // a single sided line is terminal, so it must mark ends
markfloor = markceiling = true; markfloor = markceiling = true;
@ -2150,7 +2160,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
fixed_t texheight; fixed_t texheight;
// top texture // top texture
toptexture = R_GetTextureNum(sidedef->toptexture); toptexture = R_GetTextureNum(sidedef->toptexture);
topbrightmap = R_GetTextureBrightmap(toptexture); topbrightmapped = R_TextureHasBrightmap(toptexture);
texheight = textureheight[toptexture]; texheight = textureheight[toptexture];
if (!(linedef->flags & ML_SKEWTD)) if (!(linedef->flags & ML_SKEWTD))
@ -2179,7 +2189,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{ {
// bottom texture // bottom texture
bottomtexture = R_GetTextureNum(sidedef->bottomtexture); bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
bottombrightmap = R_GetTextureBrightmap(bottomtexture); bottombrightmapped = R_TextureHasBrightmap(bottomtexture);
if (!(linedef->flags & ML_SKEWTD)) if (!(linedef->flags & ML_SKEWTD))
{ {

View file

@ -50,6 +50,7 @@ INT32 numtextures = 0; // total number of textures found,
texture_t **textures = NULL; texture_t **textures = NULL;
UINT32 **texturecolumnofs; // column offset lookup table for each texture UINT32 **texturecolumnofs; // column offset lookup table for each texture
UINT8 **texturecache; // graphics data for each generated full-size texture UINT8 **texturecache; // graphics data for each generated full-size texture
UINT8 **texturebrightmapcache; // graphics data for brightmap converted for use with a specific texture
INT32 *texturewidth; INT32 *texturewidth;
fixed_t *textureheight; // needed for texture pegging fixed_t *textureheight; // needed for texture pegging
@ -249,6 +250,50 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache
} }
} }
static UINT8 *R_AllocateTextureBlock(size_t blocksize, UINT8 **user)
{
texturememory += blocksize;
return Z_Malloc(blocksize, PU_CACHE, user);
}
static UINT8 *R_AllocateDummyTextureBlock(size_t width, UINT8 **user)
{
// Allocate dummy data. Keep 4-bytes aligned.
// Column offsets will be initialized to 0, which points to the 0xff byte (empty column flag).
size_t blocksize = 4 + (width * 4);
UINT8 *block = R_AllocateTextureBlock(blocksize, user);
memset(block, 0, blocksize);
block[0] = 0xff;
return block;
}
static boolean R_CheckTextureLumpLength(texture_t *texture, size_t patch)
{
UINT16 wadnum = texture->patches[patch].wad;
UINT16 lumpnum = texture->patches[patch].lump;
size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
// The header does not exist
if (lumplength < offsetof(softwarepatch_t, columnofs))
{
CONS_Alert(
CONS_ERROR,
"%.8s: texture lump data is too small. Expected %s bytes, got %s. (%s)\n",
texture->name,
sizeu1(offsetof(softwarepatch_t, columnofs)),
sizeu2(lumplength),
wadfiles[wadnum]->lumpinfo[lumpnum].fullname
);
return false;
}
return true;
}
// //
// R_GenerateTexture // R_GenerateTexture
// //
@ -297,22 +342,11 @@ UINT8 *R_GenerateTexture(size_t texnum)
lumplength = W_LumpLengthPwad(wadnum, lumpnum); lumplength = W_LumpLengthPwad(wadnum, lumpnum);
// The header does not exist // The header does not exist
if (lumplength < offsetof(softwarepatch_t, columnofs)) if (R_CheckTextureLumpLength(texture, 0) == false)
{ {
CONS_Alert( block = R_AllocateDummyTextureBlock(texture->width, &texturecache[texnum]);
CONS_ERROR,
"%.8s: texture lump data is too small. Expected %s bytes, got %s. (%s)\n",
texture->name,
sizeu1(offsetof(softwarepatch_t, columnofs)),
sizeu2(lumplength),
wadfiles[wadnum]->lumpinfo[lumpnum].fullname
);
// Allocate dummy data. Keep 4-bytes aligned.
// Column offsets will be initialized to 0, which points to the 0xff byte (empty column flag).
block = Z_Calloc(4 + (texture->width * 4), PU_CACHE, &texturecache[texnum]);
block[0] = 0xff;
texturecolumnofs[texnum] = (UINT32*)&block[4]; texturecolumnofs[texnum] = (UINT32*)&block[4];
textures[texnum]->holes = true;
return block; return block;
} }
@ -511,6 +545,202 @@ UINT8 *R_GenerateTextureAsFlat(size_t texnum)
return texture->flat; return texture->flat;
} }
// This function writes a column to p, using the posts from
// tcol, but the pixel values from bcol. If bcol is larger
// than tcol, the pixels are cropped. If bcol is smaller than
// tcol, the empty space is filled with TRANSPARENTPIXEL.
static void R_ConvertBrightmapColumn(UINT8 *p, const column_t *tcol, const column_t *bcol)
{
/*
___t1
|
| ___b1
| |
| |
|__t2 |
| |__b2
|
| ___b3
|__t3 |
|
___t4 |
| |__b4
|__t5
___t6
|__t7
*/
// copy post header
memcpy(&p[-3], tcol, 3);
INT32 ttop = tcol->topdelta;
INT32 btop = bcol->topdelta;
INT32 y = ttop;
while (tcol->topdelta != 0xff && bcol->topdelta != 0xff)
{
INT32 tbot = ttop + tcol->length;
INT32 bbot = btop + bcol->length;
INT32 n;
// t1 to b1
// b2 to b3
// --------
// The brightmap column starts below the
// texture column, so pad it with black
// pixels.
n = max(0, min(btop, tbot) - y);
memset(&p[y - ttop], TRANSPARENTPIXEL, n);
y += n;
// b1 to t2
// t2 to b2
// b3 to t3
// t4 to b4
// --------
// Copy parts of the brightmap column which
// line up with the texture column.
n = max(0, min(bbot, tbot) - y);
memcpy(&p[y - ttop], (const UINT8*)bcol + 3 + (y - btop), n);
y += n;
if (y == tbot)
{
p += 4 + tcol->length;
tcol = (const column_t*)((const UINT8*)tcol + 4 + tcol->length);
memcpy(&p[-3], tcol, 3); // copy post header
// Tall patches add the topdelta if it is less
// than the running topdelta.
ttop = tcol->topdelta <= ttop ? ttop + tcol->topdelta : tcol->topdelta;
y = ttop;
}
if (y >= bbot)
{
bcol = (const column_t*)((const UINT8*)bcol + 4 + bcol->length);
btop = bcol->topdelta <= btop ? btop + bcol->topdelta : bcol->topdelta; // tall patches
}
}
if (tcol->topdelta != 0xff)
{
// b4 to t5
// t6 to t7
// --------
// The texture column continues past the end
// of the brightmap column, so pad it with
// black pixels.
y -= ttop;
memset(&p[y], TRANSPARENTPIXEL, tcol->length - y);
while
(
(
p += 4 + tcol->length,
tcol = (const column_t*)((const UINT8*)tcol + 4 + tcol->length)
)->topdelta != 0xff
)
{
memcpy(&p[-3], tcol, 3); // copy post header
memset(p, TRANSPARENTPIXEL, tcol->length);
}
}
p[-3] = 0xff;
}
// Remember, this function must generate a texture that
// matches the layout of texnum. It must have the same width
// and same columns. Only the pixels that overlap are copied
// from the brightmap texture.
UINT8 *R_GenerateTextureBrightmap(size_t texnum)
{
texture_t *texture = textures[texnum];
texture_t *bright = textures[R_GetTextureBrightmap(texnum)];
if (R_TextureHasBrightmap(texnum) && bright->patchcount > 1)
{
CONS_Alert(
CONS_WARNING,
"%.8s: BRIGHTMAP should not be a composite texture. Only using the first patch.\n",
bright->name
);
}
if (R_CheckTextureLumpLength(texture, 0) == false)
{
return R_AllocateDummyTextureBlock(texture->width, &texturebrightmapcache[texnum]);
}
R_CheckTextureCache(texnum);
softwarepatch_t *patch = NULL;
INT32 bmap_width = 0;
column_t empty = {0xff, 0};
if (R_TextureHasBrightmap(texnum) && R_CheckTextureLumpLength(bright, 0))
{
patch = W_CacheLumpNumPwad(bright->patches[0].wad, bright->patches[0].lump, PU_STATIC);
bmap_width = SHORT(patch->width);
}
UINT8 *block;
if (texture->holes)
{
block = R_AllocateTextureBlock(
W_LumpLengthPwad(texture->patches[0].wad, texture->patches[0].lump),
&texturebrightmapcache[texnum]
);
INT32 x;
for (x = 0; x < texture->width; ++x)
{
const column_t *tcol = (column_t*)(R_GetColumn(texnum, x) - 3);
const column_t *bcol = x < bmap_width ? (column_t*)((UINT8*)patch + LONG(patch->columnofs[x])) : &empty;
R_ConvertBrightmapColumn(block + LONG(texturecolumnofs[texnum][x]), tcol, bcol);
}
}
else
{
// Allocate the same size as composite textures.
size_t blocksize = (texture->width * 4) + (texture->width * texture->height) + 1;
block = R_AllocateTextureBlock(blocksize, &texturebrightmapcache[texnum]);
memset(block, TRANSPARENTPIXEL, blocksize); // Transparency hack
texpatch_t origin = {0};
INT32 x;
for (x = 0; x < texture->width; ++x)
{
R_DrawColumnInCache(
x < bmap_width ? (column_t*)((UINT8*)patch + LONG(patch->columnofs[x])) : &empty,
block + LONG(texturecolumnofs[texnum][x]),
&origin,
texture->height,
patch->height
);
}
}
Z_Free(patch);
return block;
}
// //
// R_GetTextureNum // R_GetTextureNum
// //
@ -539,6 +769,11 @@ INT32 R_GetTextureBrightmap(INT32 texnum)
return texturebrightmaps[texnum]; return texturebrightmaps[texnum];
} }
boolean R_TextureHasBrightmap(INT32 texnum)
{
return R_GetTextureBrightmap(texnum) != 0;
}
// //
// R_CheckTextureCache // R_CheckTextureCache
// //
@ -551,12 +786,8 @@ void R_CheckTextureCache(INT32 tex)
R_GenerateTexture(tex); R_GenerateTexture(tex);
} }
// static inline INT32 wrap_column(fixed_t tex, INT32 col)
// R_GetColumn
//
UINT8 *R_GetColumn(fixed_t tex, INT32 col)
{ {
UINT8 *data;
INT32 width = texturewidth[tex]; INT32 width = texturewidth[tex];
if (width & (width - 1)) if (width & (width - 1))
@ -564,11 +795,29 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col)
else else
col &= (width - 1); col &= (width - 1);
data = texturecache[tex]; return col;
if (!data) }
data = R_GenerateTexture(tex);
return data + LONG(texturecolumnofs[tex][col]); //
// R_GetColumn
//
UINT8 *R_GetColumn(fixed_t tex, INT32 col)
{
if (!texturecache[tex])
R_GenerateTexture(tex);
return texturecache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]);
}
//
// R_GetBrightmapColumn
//
UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col)
{
if (!texturebrightmapcache[tex])
R_GenerateTextureBrightmap(tex);
return texturebrightmapcache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]);
} }
void *R_GetFlat(lumpnum_t flatlumpnum) void *R_GetFlat(lumpnum_t flatlumpnum)
@ -1099,6 +1348,7 @@ static void R_AllocateTextures(INT32 add)
recallocuser(&texturecolumnofs, oldsize, newsize); recallocuser(&texturecolumnofs, oldsize, newsize);
// Allocate texture referencing cache. // Allocate texture referencing cache.
recallocuser(&texturecache, oldsize, newsize); recallocuser(&texturecache, oldsize, newsize);
recallocuser(&texturebrightmapcache, oldsize, newsize);
// Allocate texture width table. // Allocate texture width table.
recallocuser(&texturewidth, oldsize, newsize); recallocuser(&texturewidth, oldsize, newsize);
// Allocate texture height table. // Allocate texture height table.
@ -1113,8 +1363,8 @@ static void R_AllocateTextures(INT32 add)
// R_FlushTextureCache relies on the user for // R_FlushTextureCache relies on the user for
// Z_Free, texturecache has been reallocated so the // Z_Free, texturecache has been reallocated so the
// user is now garbage memory. // user is now garbage memory.
Z_SetUser(texturecache[i], Z_SetUser(texturecache[i], (void**)&texturecache[i]);
(void**)&texturecache[i]); Z_SetUser(texturebrightmapcache[i], (void**)&texturebrightmapcache[i]);
} }
while (i < newtextures) while (i < newtextures)

View file

@ -80,6 +80,7 @@ extern fixed_t *textureheight; // needed for texture pegging
extern UINT32 **texturecolumnofs; // column offset lookup table for each texture extern UINT32 **texturecolumnofs; // column offset lookup table for each texture
extern UINT8 **texturecache; // graphics data for each generated full-size texture extern UINT8 **texturecache; // graphics data for each generated full-size texture
extern UINT8 **texturebrightmapcache; // graphics data for brightmap converted for use with a specific texture
// Load TEXTURES definitions, create lookup tables // Load TEXTURES definitions, create lookup tables
void R_LoadTextures(void); void R_LoadTextures(void);
@ -89,14 +90,17 @@ void R_FlushTextureCache(void);
// Texture generation // Texture generation
UINT8 *R_GenerateTexture(size_t texnum); UINT8 *R_GenerateTexture(size_t texnum);
UINT8 *R_GenerateTextureAsFlat(size_t texnum); UINT8 *R_GenerateTextureAsFlat(size_t texnum);
UINT8 *R_GenerateTextureBrightmap(size_t texnum);
INT32 R_GetTextureNum(INT32 texnum); INT32 R_GetTextureNum(INT32 texnum);
INT32 R_GetTextureBrightmap(INT32 texnum); INT32 R_GetTextureBrightmap(INT32 texnum);
boolean R_TextureHasBrightmap(INT32 texnum);
void R_CheckTextureCache(INT32 tex); void R_CheckTextureCache(INT32 tex);
void R_ClearTextureNumCache(boolean btell); void R_ClearTextureNumCache(boolean btell);
// Retrieve texture data. // Retrieve texture data.
void *R_GetLevelFlat(levelflat_t *levelflat); void *R_GetLevelFlat(levelflat_t *levelflat);
UINT8 *R_GetColumn(fixed_t tex, INT32 col); UINT8 *R_GetColumn(fixed_t tex, INT32 col);
UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col);
void *R_GetFlat(lumpnum_t flatnum); void *R_GetFlat(lumpnum_t flatnum);
boolean R_CheckPowersOfTwo(void); boolean R_CheckPowersOfTwo(void);

View file

@ -900,6 +900,14 @@ static void R_DrawVisSprite(vissprite_t *vis)
} }
// Prevent an out of bounds error // Prevent an out of bounds error
//
// FIXME: The following check doesn't account for
// differences in transparency between the patches.
//
// Sprite BRIGHTMAPs should be converted on load,
// as like textures. I'm too tired to bother with it
// right now, though.
//
if (bmpatch && (bmpatch->width != patch->width || if (bmpatch && (bmpatch->width != patch->width ||
bmpatch->height != patch->height)) bmpatch->height != patch->height))
{ {