Skip to content

Commit

Permalink
Strife: add true color support (fabiangreffrath#1183)
Browse files Browse the repository at this point in the history
* Initial implementation

* Fix crash on drawing view border

* Sigil weapon effect working

* crispy_truecolor config variable

* Btightmaps working!

* Blending and alt blending functions

* Proper translucensy values for columns and walls

* Graphical startup working

* Get rid of few TODOs

* Better logics for brightmaps emulation

* Update screen wiping code

It's working technically now, but the problem with infinite loop of comparing old and new screen data have to be resolved.

* Fix possible infinite loop in crossfading, make it work in TrueColor

* Proper implementation of crossfading effect

Now it looks and feels like vanilla!

* Fix introduction sequence for both renders

* Small corrections

1) No need for separated R_InitPalColors() function. (Re-)filling pal_color[] array must be done along with colormaps[] as it's related to gamma-correction.
2) Redraw side views of screen border on toggling gamma-correction.

* Simplify overlay blending functions

* Make fail-safe crossfade counter static, better naming

* Remove redundant brackets, fix typo

* Simplify COLORMAP's brightmapped colors calculation

* Small styling corrections

* Fix translated+translucent columns drawing

* Proper memory size allocation for wiping effect

Co-Authored-By: Fabian Greffrath <[email protected]>

---------

Co-authored-by: Fabian Greffrath <[email protected]>
  • Loading branch information
JNechaevsky and fabiangreffrath authored Apr 19, 2024
1 parent 0d91a32 commit b9f69a5
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 106 deletions.
6 changes: 3 additions & 3 deletions src/doom/r_things.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ R_DrawVisSprite

colfunc = basecolfunc;
#ifdef CRISPY_TRUECOLOR
blendfunc = I_BlendOver;
blendfunc = I_BlendOverTranmap;
#endif
}

Expand Down Expand Up @@ -817,7 +817,7 @@ void R_ProjectSprite (mobj_t* thing)
// [crispy] translucent sprites
if (thing->flags & MF_TRANSLUCENT)
{
vis->blendfunc = (thing->frame & FF_FULLBRIGHT) ? I_BlendAdd : I_BlendOver;
vis->blendfunc = (thing->frame & FF_FULLBRIGHT) ? I_BlendAdd : I_BlendOverTranmap;
}
#endif
}
Expand Down Expand Up @@ -1079,7 +1079,7 @@ void R_DrawPSprite (pspdef_t* psp, psprnum_t psprnum) // [crispy] differentiate
{
vis->mobjflags |= MF_TRANSLUCENT;
#ifdef CRISPY_TRUECOLOR
vis->blendfunc = I_BlendOver; // I_BlendAdd;
vis->blendfunc = I_BlendOverTranmap; // I_BlendAdd;
#endif
}

Expand Down
42 changes: 25 additions & 17 deletions src/i_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ static SDL_Texture *graypane = NULL;
static SDL_Texture *orngpane = NULL;
static int pane_alpha;
static unsigned int rmask, gmask, bmask, amask; // [crispy] moved up here
static const uint8_t blend_alpha = 0xa8;
static const uint8_t blend_alpha_tinttab = 0x60; // 96
static const uint8_t blend_alpha_alttinttab = 0x8E; // 142
extern pixel_t* pal_color; // [crispy] evil hack to get FPS dots working as in Vanilla
#else
static SDL_Color palette[256];
Expand Down Expand Up @@ -2136,36 +2133,47 @@ const pixel_t I_BlendDark (const pixel_t bg, const int d)
return amask | sag | srb;
}

const pixel_t I_BlendOver (const pixel_t bg, const pixel_t fg)
// [crispy] Main overlay blending function
const pixel_t I_BlendOver (const pixel_t bg, const pixel_t fg, const int amount)
{
const uint32_t r = ((blend_alpha * (fg & rmask) + (0xff - blend_alpha) * (bg & rmask)) >> 8) & rmask;
const uint32_t g = ((blend_alpha * (fg & gmask) + (0xff - blend_alpha) * (bg & gmask)) >> 8) & gmask;
const uint32_t b = ((blend_alpha * (fg & bmask) + (0xff - blend_alpha) * (bg & bmask)) >> 8) & bmask;
const uint32_t r = ((amount * (fg & rmask) + (0xff - amount) * (bg & rmask)) >> 8) & rmask;
const uint32_t g = ((amount * (fg & gmask) + (0xff - amount) * (bg & gmask)) >> 8) & gmask;
const uint32_t b = ((amount * (fg & bmask) + (0xff - amount) * (bg & bmask)) >> 8) & bmask;

return amask | r | g | b;
}

// [crispy] TRANMAP blending emulation, used for Doom
const pixel_t I_BlendOverTranmap (const pixel_t bg, const pixel_t fg)
{
return I_BlendOver(bg, fg, 224); // 168 (66% opacity)
}

// [crispy] TINTTAB blending emulation, used for Heretic and Hexen
const pixel_t I_BlendOverTinttab (const pixel_t bg, const pixel_t fg)
{
const uint32_t r = ((blend_alpha_tinttab * (fg & rmask) + (0xff - blend_alpha_tinttab) * (bg & rmask)) >> 8) & rmask;
const uint32_t g = ((blend_alpha_tinttab * (fg & gmask) + (0xff - blend_alpha_tinttab) * (bg & gmask)) >> 8) & gmask;
const uint32_t b = ((blend_alpha_tinttab * (fg & bmask) + (0xff - blend_alpha_tinttab) * (bg & bmask)) >> 8) & bmask;

return amask | r | g | b;
return I_BlendOver(bg, fg, 0x60); // 96 (38% opacity)
}

// [crispy] More opaque ("Alt") TINTTAB blending emulation, used for Hexen's MF_ALTSHADOW drawing
const pixel_t I_BlendOverAltTinttab (const pixel_t bg, const pixel_t fg)
{
const uint32_t r = ((blend_alpha_alttinttab * (fg & rmask) + (0xff - blend_alpha_alttinttab) * (bg & rmask)) >> 8) & rmask;
const uint32_t g = ((blend_alpha_alttinttab * (fg & gmask) + (0xff - blend_alpha_alttinttab) * (bg & gmask)) >> 8) & gmask;
const uint32_t b = ((blend_alpha_alttinttab * (fg & bmask) + (0xff - blend_alpha_alttinttab) * (bg & bmask)) >> 8) & bmask;
return I_BlendOver(bg, fg, 0x8E); // 142 (56% opacity)
}

return amask | r | g | b;
// [crispy] More opaque XLATAB blending emulation, used for Strife
const pixel_t I_BlendOverXlatab (const pixel_t bg, const pixel_t fg)
{
return I_BlendOver(bg, fg, 0xC0); // 192 (75% opacity)
}

// [crispy] Less opaque ("Alt") XLATAB blending emulation, used for Strife
const pixel_t I_BlendOverAltXlatab (const pixel_t bg, const pixel_t fg)
{
return I_BlendOver(bg, fg, 0x40); // 64 (25% opacity)
}

const pixel_t (*blendfunc) (const pixel_t fg, const pixel_t bg) = I_BlendOver;
const pixel_t (*blendfunc) (const pixel_t fg, const pixel_t bg) = I_BlendOverTranmap;

const pixel_t I_MapRGB (const uint8_t r, const uint8_t g, const uint8_t b)
{
Expand Down
31 changes: 20 additions & 11 deletions src/strife/am_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,12 @@ AM_drawFline_Vanilla
return;
}

#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
#define PUTDOT_RAW(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
#ifndef CRISPY_TRUECOLOR
#define PUTDOT(xx,yy,cc) PUTDOT_RAW(xx,yy,cc)
#else
#define PUTDOT(xx,yy,cc) PUTDOT_RAW(xx,yy,(pal_color[(cc)]))
#endif

dx = fl->b.x - fl->a.x;
ax = 2 * (dx<0 ? -dx : dx);
Expand Down Expand Up @@ -1307,7 +1312,7 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
the line and so needs no weighting */
/* Always write the raw color value because we've already performed the necessary lookup
* into colormap */
PUTDOT(X0, Y0, BaseColor[0]);
PUTDOT_RAW(X0, Y0, BaseColor[0]);

if ((DeltaX = X1 - X0) >= 0)
{
Expand All @@ -1327,7 +1332,7 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
while (DeltaX-- != 0)
{
X0 += XDir;
PUTDOT(X0, Y0, BaseColor[0]);
PUTDOT_RAW(X0, Y0, BaseColor[0]);
}
return;
}
Expand All @@ -1337,7 +1342,7 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
do
{
Y0++;
PUTDOT(X0, Y0, BaseColor[0]);
PUTDOT_RAW(X0, Y0, BaseColor[0]);
}
while (--DeltaY != 0);
return;
Expand All @@ -1349,7 +1354,7 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
{
X0 += XDir;
Y0++;
PUTDOT(X0, Y0, BaseColor[0]);
PUTDOT_RAW(X0, Y0, BaseColor[0]);
}
while (--DeltaY != 0);
return;
Expand Down Expand Up @@ -1383,12 +1388,12 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
PUTDOT(X0, Y0, BaseColor[Weighting]);
PUTDOT(X0 + XDir, Y0, BaseColor[(Weighting ^ WeightingComplementMask)]);
PUTDOT_RAW(X0, Y0, BaseColor[Weighting]);
PUTDOT_RAW(X0 + XDir, Y0, BaseColor[(Weighting ^ WeightingComplementMask)]);
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
PUTDOT(X1, Y1, BaseColor[0]);
PUTDOT_RAW(X1, Y1, BaseColor[0]);
return;
}
/* It's an X-major line; calculate 16-bit fixed-point fractional part of a
Expand All @@ -1410,13 +1415,13 @@ static void AM_drawFline_Smooth(fline_t* fl, int color)
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
PUTDOT(X0, Y0, BaseColor[Weighting]);
PUTDOT(X0, Y0 + 1, BaseColor[(Weighting ^ WeightingComplementMask)]);
PUTDOT_RAW(X0, Y0, BaseColor[Weighting]);
PUTDOT_RAW(X0, Y0 + 1, BaseColor[(Weighting ^ WeightingComplementMask)]);

}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
PUTDOT(X1, Y1, BaseColor[0]);
PUTDOT_RAW(X1, Y1, BaseColor[0]);
}

//
Expand Down Expand Up @@ -1885,7 +1890,11 @@ void AM_Drawer (void)

if (!crispy->automapoverlay)
{
#ifndef CRISPY_TRUECOLOR
AM_clearFB(BACKGROUND);
#else
AM_clearFB(pal_color[BACKGROUND]);
#endif
pspr_interp = false; // [crispy] interpolate weapon bobbing
}

Expand Down
12 changes: 12 additions & 0 deletions src/strife/d_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,11 @@ void D_Display (void)

// clean up border stuff
if (gamestate != oldgamestate && gamestate != GS_LEVEL)
#ifndef CRISPY_TRUECOLOR
I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
#else
I_SetPalette (0);
#endif

// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL)
Expand Down Expand Up @@ -537,6 +541,9 @@ void D_BindVariables(void)
M_BindIntVariable("crispy_soundfix", &crispy->soundfix);
M_BindIntVariable("crispy_soundfull", &crispy->soundfull);
M_BindIntVariable("crispy_soundmono", &crispy->soundmono);
#ifdef CRISPY_TRUECOLOR
M_BindIntVariable("crispy_truecolor", &crispy->truecolor);
#endif
M_BindIntVariable("crispy_uncapped", &crispy->uncapped);
M_BindIntVariable("crispy_vsync", &crispy->vsync);
M_BindIntVariable("crispy_widescreen", &crispy->widescreen);
Expand Down Expand Up @@ -2024,6 +2031,11 @@ void D_DoomMain (void)

I_GraphicsCheckCommandLine();

// [crispy] Initialize and generate gamma-correction levels and
// colormaps/pal_color arrays before introduction sequence.
I_SetGammaTable();
R_InitColormaps();

// haleyjd 20110206 [STRIFE] Startup the introduction sequence
D_InitIntroSequence();

Expand Down
61 changes: 38 additions & 23 deletions src/strife/f_wipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "z_zone.h"
#include "i_video.h"
#include "v_trans.h" // [crispy] blending functions
#include "v_video.h"
#include "m_random.h"

Expand All @@ -37,28 +38,30 @@
// when zero, stop the wipe
static boolean go = 0;

static byte* wipe_scr_start;
static byte* wipe_scr_end;
static byte* wipe_scr;
static pixel_t* wipe_scr_start;
static pixel_t* wipe_scr_end;
static pixel_t* wipe_scr;

// [crispy] Additional fail-safe counter for performing crossfade effect.
static int fade_counter;

void
wipe_shittyColMajorXform
( short* array,
( dpixel_t* array,
int width,
int height )
{
int x;
int y;
short* dest;
dpixel_t* dest;

dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
dest = (dpixel_t*) Z_Malloc(width*height*sizeof(*dest), PU_STATIC, 0);

for(y=0;y<height;y++)
for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x];

memcpy(array, dest, width*height*2);
memcpy(array, dest, width*height*sizeof(*dest));

Z_Free(dest);

Expand All @@ -71,7 +74,10 @@ wipe_initColorXForm
int height,
int ticks )
{
memcpy(wipe_scr, wipe_scr_start, width*height);
memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr));
// [crispy] arm fail-safe crossfade counter with
// 13 screen transitions, "zero" count won't be used.
fade_counter = 14;
return 0;
}

Expand All @@ -88,18 +94,27 @@ wipe_doColorXForm
int height,
int ticks )
{
byte *cur_screen = wipe_scr;
byte *end_screen = wipe_scr_end;
pixel_t *cur_screen = wipe_scr;
pixel_t *end_screen = wipe_scr_end;
int pix = width*height;
int i;
boolean changed = false;

// [crispy] reduce fail-safe crossfade counter tics
fade_counter--;

for(i = pix; i > 0; i--)
{
if(*cur_screen != *end_screen)
if(*cur_screen != *end_screen && fade_counter)
{
changed = true;
#ifndef CRISPY_TRUECOLOR
*cur_screen = xlatab[(*cur_screen << 8) + *end_screen];
#else
// [crispy] perform crossfading effect with 13 given opacity steps, multipled by 19:
// 247, 228, 209, 190, 171, 152, 133, 114, 95, 76, 57, 38, 19
*cur_screen = I_BlendOver(*end_screen, *cur_screen, fade_counter * 19);
#endif
}
++cur_screen;
++end_screen;
Expand Down Expand Up @@ -130,12 +145,12 @@ wipe_initMelt
int i, r;

// copy start screen to main screen
memcpy(wipe_scr, wipe_scr_start, width*height);
memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr));

// makes this wipe faster (in theory)
// to have stuff in column-major format
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
wipe_shittyColMajorXform((dpixel_t*)wipe_scr_start, width/2, height);
wipe_shittyColMajorXform((dpixel_t*)wipe_scr_end, width/2, height);

// setup initial column positions
// (y<0 => not ready to scroll yet)
Expand Down Expand Up @@ -163,8 +178,8 @@ wipe_doMelt
int dy;
int idx;

short* s;
short* d;
dpixel_t* s;
dpixel_t* d;
boolean done = true;

width/=2;
Expand All @@ -181,17 +196,17 @@ wipe_doMelt
{
dy = (y[i] < 16) ? y[i]+1 : 8;
if (y[i]+dy >= height) dy = height - y[i];
s = &((short *)wipe_scr_end)[i*height+y[i]];
d = &((short *)wipe_scr)[y[i]*width+i];
s = &((dpixel_t *)wipe_scr_end)[i*height+y[i]];
d = &((dpixel_t *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=dy;j;j--)
{
d[idx] = *(s++);
idx += width;
}
y[i] += dy;
s = &((short *)wipe_scr_start)[i*height];
d = &((short *)wipe_scr)[y[i]*width+i];
s = &((dpixel_t *)wipe_scr_start)[i*height];
d = &((dpixel_t *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=height-y[i];j;j--)
{
Expand Down Expand Up @@ -227,7 +242,7 @@ wipe_StartScreen
int width,
int height )
{
wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_start), PU_STATIC, NULL);
I_ReadScreen(wipe_scr_start);
return 0;
}
Expand All @@ -240,7 +255,7 @@ wipe_EndScreen
int width,
int height )
{
wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_end), PU_STATIC, NULL);
I_ReadScreen(wipe_scr_end);
V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr.
return 0;
Expand Down Expand Up @@ -268,7 +283,7 @@ wipe_ScreenWipe
{
go = 1;
// haleyjd 20110629 [STRIFE]: We *must* use a temp buffer here.
wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG
wipe_scr = (pixel_t *) Z_Malloc(width*height*sizeof(*wipe_scr), PU_STATIC, 0); // DEBUG
//wipe_scr = I_VideoBuffer;
(*wipes[wipeno*3])(width, height, ticks);
}
Expand Down
Loading

0 comments on commit b9f69a5

Please sign in to comment.