diff --git a/src/crispy.c b/src/crispy.c index e2544d498..46878fbd0 100644 --- a/src/crispy.c +++ b/src/crispy.c @@ -31,6 +31,7 @@ static crispy_t crispy_s = { #ifdef CRISPY_TRUECOLOR .smoothlight = 1, .truecolor = 1, + .truecolorblend = 1, #endif .vsync = 1, .widescreen = 1, // match screen by default diff --git a/src/crispy.h b/src/crispy.h index de6e702cc..01e69382b 100644 --- a/src/crispy.h +++ b/src/crispy.h @@ -81,6 +81,7 @@ typedef struct int translucency; #ifdef CRISPY_TRUECOLOR int truecolor; + int truecolorblend; #endif int uncapped; int vsync; @@ -243,6 +244,13 @@ enum NUM_SECRETMESSAGE }; +enum +{ + TRUECOLORBLEND_OFF, + TRUECOLORBLEND_ON, + NUM_TRUECOLORBLEND +}; + enum { WIDGETS_OFF, diff --git a/src/doom/d_main.c b/src/doom/d_main.c index 5b782bfa8..92a3ddd96 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -483,6 +483,7 @@ void D_BindVariables(void) M_BindIntVariable("crispy_translucency", &crispy->translucency); #ifdef CRISPY_TRUECOLOR M_BindIntVariable("crispy_truecolor", &crispy->truecolor); + M_BindIntVariable("crispy_truecolorblend", &crispy->truecolorblend); #endif M_BindIntVariable("crispy_uncapped", &crispy->uncapped); M_BindIntVariable("crispy_vsync", &crispy->vsync); diff --git a/src/doom/m_crispy.c b/src/doom/m_crispy.c index 3fcced9a0..50ad5d09c 100644 --- a/src/doom/m_crispy.c +++ b/src/doom/m_crispy.c @@ -155,6 +155,12 @@ multiitem_t multiitem_sndchannels[4] = {32, "32"}, }; +multiitem_t multiitem_truecolorblend[NUM_TRUECOLORBLEND] = +{ + {TRUECOLORBLEND_OFF, "speed"}, + {TRUECOLORBLEND_ON, "quality"}, +}; + multiitem_t multiitem_widgets[NUM_WIDGETS] = { {WIDGETS_OFF, "never"}, @@ -573,6 +579,17 @@ void M_CrispyToggleTranslucency(int choice) ChangeSettingEnum(&crispy->translucency, choice, NUM_TRANSLUCENCY); } +#ifdef CRISPY_TRUECOLOR +void M_CrispyToggleTrueColorBlend(int choice) +{ + choice = 0; + crispy->truecolorblend = !crispy->truecolorblend; + + // [crispy] re-set pointers to blending functions + R_InitBlendQuality(); +} +#endif + void M_CrispyToggleUncapped(int choice) { choice = 0; diff --git a/src/doom/m_crispy.h b/src/doom/m_crispy.h index 60cb91f0f..d9aeb54a4 100644 --- a/src/doom/m_crispy.h +++ b/src/doom/m_crispy.h @@ -42,6 +42,7 @@ extern multiitem_t multiitem_sndchannels[4]; extern multiitem_t multiitem_secretmessage[NUM_SECRETMESSAGE]; extern multiitem_t multiitem_statsformat[NUM_STATSFORMATS]; extern multiitem_t multiitem_translucency[NUM_TRANSLUCENCY]; +extern multiitem_t multiitem_truecolorblend[NUM_TRUECOLORBLEND]; extern multiitem_t multiitem_widgets[NUM_WIDGETS]; extern multiitem_t multiitem_widescreen[NUM_RATIOS]; extern multiitem_t multiitem_difficulties[NUM_SKILLS]; @@ -84,6 +85,7 @@ extern void M_CrispyToggleSoundfixes(int choice); extern void M_CrispyToggleSoundMono(int choice); extern void M_CrispyToggleStatsFormat(int choice); extern void M_CrispyToggleTranslucency(int choice); +extern void M_CrispyToggleTrueColorBlend(int choice); extern void M_CrispyToggleUncapped(int choice); extern void M_CrispyToggleVsync(int choice); extern void M_CrispyToggleWidescreen(int choice); diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c index 8af456c72..0ea1405c2 100644 --- a/src/doom/m_menu.c +++ b/src/doom/m_menu.c @@ -468,17 +468,19 @@ enum crispness_fpslimit, crispness_vsync, crispness_smoothscaling, - crispness_sep_rendering_, crispness_sep_visual, crispness_coloredhud, crispness_translucency, +#ifdef CRISPY_TRUECOLOR + crispness_truecolorblend, +#endif crispness_smoothlight, crispness_brightmaps, crispness_coloredblood, crispness_flipcorpses, - crispness_sep_visual_, + crispness1_sep_empty, crispness1_next, crispness1_prev, crispness1_end @@ -494,9 +496,11 @@ static menuitem_t Crispness1Menu[]= {3,"", M_CrispyToggleVsync,'v'}, {3,"", M_CrispyToggleSmoothScaling,'s'}, {-1,"",0,'\0'}, - {-1,"",0,'\0'}, {3,"", M_CrispyToggleColoredhud,'c'}, {3,"", M_CrispyToggleTranslucency,'e'}, +#ifdef CRISPY_TRUECOLOR + {3,"", M_CrispyToggleTrueColorBlend,'t'}, +#endif {3,"", M_CrispyToggleSmoothLighting,'s'}, {3,"", M_CrispyToggleBrightmaps,'b'}, {3,"", M_CrispyToggleColoredblood,'c'}, @@ -523,7 +527,6 @@ enum crispness_soundfix, crispness_sndchannels, crispness_soundmono, - crispness_sep_audible_, crispness_sep_navigational, crispness_extautomap, @@ -533,8 +536,8 @@ enum crispness_leveltime, crispness_playercoords, crispness_secretmessage, - crispness_sep_navigational_, - + + crispness2_sep_empty, crispness2_next, crispness2_prev, crispness2_end @@ -548,7 +551,6 @@ static menuitem_t Crispness2Menu[]= {3,"", M_CrispyToggleSndChannels,'s'}, {3,"", M_CrispyToggleSoundMono,'m'}, {-1,"",0,'\0'}, - {-1,"",0,'\0'}, {3,"", M_CrispyToggleExtAutomap,'e'}, {3,"", M_CrispyToggleSmoothMap,'m'}, {3,"", M_CrispyToggleAutomapstats,'s'}, @@ -581,15 +583,14 @@ enum crispness_pitch, crispness_neghealth, crispness_defaultskill, - crispness_sep_tactical_, crispness_sep_crosshair, crispness_crosshair, crispness_crosshairtype, crispness_crosshairhealth, crispness_crosshairtarget, - crispness_sep_crosshair_, + crispness3_sep_empty, crispness3_next, crispness3_prev, crispness3_end @@ -606,7 +607,6 @@ static menuitem_t Crispness3Menu[]= {3,"", M_CrispyToggleNeghealth,'n'}, {3,"", M_CrispyToggleDefaultSkill,'d'}, {-1,"",0,'\0'}, - {-1,"",0,'\0'}, {3,"", M_CrispyToggleCrosshair,'d'}, {3,"", M_CrispyToggleCrosshairtype,'c'}, {3,"", M_CrispyToggleCrosshairHealth,'c'}, @@ -632,15 +632,14 @@ enum crispness_freeaim, crispness_jumping, crispness_overunder, - crispness_sep_physical_, crispness_sep_demos, crispness_demotimer, crispness_demotimerdir, crispness_demobar, crispness_demousetimer, - crispness_sep_demos_, + crispness4_sep_empty, crispness4_next, crispness4_prev, crispness4_end @@ -654,7 +653,6 @@ static menuitem_t Crispness4Menu[]= {3,"", M_CrispyToggleJumping,'a'}, {3,"", M_CrispyToggleOverunder,'w'}, {-1,"",0,'\0'}, - {-1,"",0,'\0'}, {3,"", M_CrispyToggleDemoTimer,'v'}, {3,"", M_CrispyToggleDemoTimerDir,'a'}, {3,"", M_CrispyToggleDemoBar,'w'}, @@ -1574,6 +1572,9 @@ static void M_DrawCrispness1(void) M_DrawCrispnessSeparator(crispness_sep_visual, "Visual"); M_DrawCrispnessMultiItem(crispness_coloredhud, "Colorize HUD Elements", multiitem_coloredhud, crispy->coloredhud, true); M_DrawCrispnessMultiItem(crispness_translucency, "Enable Translucency", multiitem_translucency, crispy->translucency, true); +#ifdef CRISPY_TRUECOLOR + M_DrawCrispnessMultiItem(crispness_truecolorblend, "Translucency mode", multiitem_truecolorblend, crispy->truecolorblend, true); +#endif M_DrawCrispnessItem(crispness_smoothlight, "Smooth Diminishing Lighting", crispy->smoothlight, true); M_DrawCrispnessMultiItem(crispness_brightmaps, "Apply Brightmaps to", multiitem_brightmaps, crispy->brightmaps, true); M_DrawCrispnessMultiItem(crispness_coloredblood, "Colored Blood", multiitem_coloredblood, crispy->coloredblood, gameversion != exe_chex); diff --git a/src/doom/r_data.c b/src/doom/r_data.c index 9b2c18a5a..ba2056041 100644 --- a/src/doom/r_data.c +++ b/src/doom/r_data.c @@ -1350,6 +1350,12 @@ void R_InitData (void) R_InitHSVColors (); #ifndef CRISPY_TRUECOLOR R_InitTranMap(); // [crispy] prints a mark itself +#else + // [crispy] Initialize blending maps for tablified additive and + // overlay translucency, used by TrueColor renderer. + R_InitBlendMaps(doom); + // [crispy] Set pointers to blending functions. + R_InitBlendQuality(); #endif } diff --git a/src/doom/r_things.c b/src/doom/r_things.c index 6f1e31a68..f23cbe5ea 100644 --- a/src/doom/r_things.c +++ b/src/doom/r_things.c @@ -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_BlendOverTranmap; + vis->blendfunc = (thing->frame & FF_FULLBRIGHT) ? I_BlendAddFunc : I_BlendOverTranmap; } #endif } diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c index c2c5ac316..6c5ffe02e 100644 --- a/src/heretic/d_main.c +++ b/src/heretic/d_main.c @@ -886,6 +886,7 @@ void D_BindVariables(void) M_BindIntVariable("crispy_soundmono", &crispy->soundmono); #ifdef CRISPY_TRUECOLOR M_BindIntVariable("crispy_truecolor", &crispy->truecolor); + M_BindIntVariable("crispy_truecolorblend", &crispy->truecolorblend); #endif M_BindIntVariable("crispy_uncapped", &crispy->uncapped); M_BindIntVariable("crispy_vsync", &crispy->vsync); diff --git a/src/heretic/mn_menu.c b/src/heretic/mn_menu.c index 0ae7d94ae..9b2b51a88 100644 --- a/src/heretic/mn_menu.c +++ b/src/heretic/mn_menu.c @@ -131,6 +131,9 @@ static boolean CrispyHires(int option); static boolean CrispyToggleWidescreen(int option); static boolean CrispySmoothing(int option); static boolean CrispyBrightmaps(int option); +#ifdef CRISPY_TRUECOLOR +static boolean CrispyToggleTrueColorBlend(int option); +#endif static boolean CrispySmoothLighting(int option); static boolean CrispySoundMono(int option); static boolean CrispySndChannels(int option); @@ -361,6 +364,12 @@ static int crispnessmenupage; #define NUM_CRISPNESS_MENUS 2 +#ifndef CRISPY_TRUECOLOR +#define NUMCRISPNESS1ITEMS 14 +#else +#define NUMCRISPNESS1ITEMS 15 +#endif + static MenuItem_t Crispness1Items[] = { {ITT_LRFUNC2, "HIGH RESOLUTION RENDERING:", CrispyHires, 0, MENU_NONE}, {ITT_LRFUNC2, "ASPECT RATIO:", CrispyToggleWidescreen, 0, MENU_NONE}, @@ -369,11 +378,12 @@ static MenuItem_t Crispness1Items[] = { {ITT_NUMFUNC, "FRAMERATE LIMIT:", CrispyFpsLimit, 0, MENU_NONE}, {ITT_LRFUNC2, "ENABLE VSYNC:", CrispyVsync, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "APPLY BRIGHTMAPS TO:", CrispyBrightmaps, 0, MENU_NONE}, +#ifdef CRISPY_TRUECOLOR + {ITT_LRFUNC2,"TRANSLUCENCY MODE:", CrispyToggleTrueColorBlend, 0, MENU_NONE}, +#endif {ITT_LRFUNC2, "SMOOTH DIMINISHING LIGHTING:", CrispySmoothLighting, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "MONO SFX:", CrispySoundMono, 0, MENU_NONE}, {ITT_LRFUNC2, "SOUND CHANNELS:", CrispySndChannels, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, @@ -383,7 +393,7 @@ static MenuItem_t Crispness1Items[] = { static Menu_t Crispness1Menu = { 68, 35, DrawCrispness, - 16, Crispness1Items, + NUMCRISPNESS1ITEMS, Crispness1Items, 0, MENU_OPTIONS }; @@ -394,7 +404,6 @@ static MenuItem_t Crispness2Items[] = { {ITT_LRFUNC2, "SHOW PLAYER COORDS:", CrispyPlayerCoords, 0, MENU_NONE}, {ITT_LRFUNC2, "REPORT REVEALED SECRETS:", CrispySecretMessage, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "FREELOOK MODE:", CrispyFreelook, 0, MENU_NONE}, {ITT_LRFUNC2, "PERMANENT MOUSELOOK:", CrispyMouselook, 0, MENU_NONE}, {ITT_LRFUNC2, "PLAYER VIEW/WEAPON BOBBING:", CrispyBobfactor, 0, MENU_NONE}, @@ -407,7 +416,7 @@ static MenuItem_t Crispness2Items[] = { static Menu_t Crispness2Menu = { 68, 35, DrawCrispness, - 13, Crispness2Items, + 12, Crispness2Items, 0, MENU_OPTIONS }; @@ -444,6 +453,14 @@ static const multiitem_t multiitem_centerweapon[NUM_CENTERWEAPON] = {CENTERWEAPON_BOB, "BOBBING"}, }; +#ifdef CRISPY_TRUECOLOR +static const multiitem_t multiitem_truecolorblend[NUM_TRUECOLORBLEND] = +{ + {TRUECOLORBLEND_OFF, "SPEED"}, + {TRUECOLORBLEND_ON, "QUALITY"}, +}; +#endif + static const multiitem_t multiitem_widescreen[NUM_RATIOS] = { {RATIO_ORIG, "ORIGINAL"}, @@ -1708,6 +1725,17 @@ static boolean CrispyBrightmaps(int option) return true; } +#ifdef CRISPY_TRUECOLOR +static boolean CrispyToggleTrueColorBlend(int option) +{ + crispy->truecolorblend = !crispy->truecolorblend; + + // [crispy] re-set pointers to blending functions + R_InitBlendQuality(); + return true; +} +#endif + static void CrispySmoothLightingHook (void) { crispy->smoothlight = !crispy->smoothlight; @@ -2980,6 +3008,8 @@ static void DrawCrispnessNumericItem(int item, int x, int y, const char *zero, static void DrawCrispness1(void) { + int y_shift = 0; + DrawCrispnessHeader("CRISPNESS 1/2"); DrawCrispnessSubheader("RENDERING", 25); @@ -3002,21 +3032,27 @@ static void DrawCrispness1(void) // Vsync DrawCrispnessItem(crispy->vsync, 167, 85); - DrawCrispnessSubheader("VISUAL", 105); + DrawCrispnessSubheader("VISUAL", 95); // Brightmaps - DrawCrispnessMultiItem(crispy->brightmaps, 213, 115, multiitem_brightmaps, false); + DrawCrispnessMultiItem(crispy->brightmaps, 213, 105, multiitem_brightmaps, false); + +#ifdef CRISPY_TRUECOLOR + y_shift += 10; + // Translucency mode + DrawCrispnessMultiItem(crispy->truecolorblend, 205, 115, multiitem_truecolorblend, false); +#endif // Smooth Diminishing Lighting - DrawCrispnessItem(crispy->smoothlight, 257, 125); + DrawCrispnessItem(crispy->smoothlight, 257, 115 + y_shift); - DrawCrispnessSubheader("AUDIBLE", 145); + DrawCrispnessSubheader("AUDIBLE", 125 + y_shift); // Mono SFX - DrawCrispnessItem(crispy->soundmono, 137, 155); + DrawCrispnessItem(crispy->soundmono, 137, 135 + y_shift); // Sound Channels - DrawCrispnessMultiItem(snd_Channels >> 4, 181, 165, multiitem_sndchannels, false); + DrawCrispnessMultiItem(snd_Channels >> 4, 181, 145 + y_shift, multiitem_sndchannels, false); } static void DrawCrispness2(void) @@ -3036,21 +3072,21 @@ static void DrawCrispness2(void) // Show secret message DrawCrispnessMultiItem(crispy->secretmessage, 250, 65, multiitem_secretmessage, false); - DrawCrispnessSubheader("TACTICAL", 85); + DrawCrispnessSubheader("TACTICAL", 75); // Freelook - DrawCrispnessMultiItem(crispy->freelook_hh, 175, 95, multiitem_freelook_hh, false); + DrawCrispnessMultiItem(crispy->freelook_hh, 175, 85, multiitem_freelook_hh, false); // Mouselook - DrawCrispnessItem(crispy->mouselook, 220, 105); + DrawCrispnessItem(crispy->mouselook, 220, 95); // Bobfactor - DrawCrispnessMultiItem(crispy->bobfactor, 265, 115, multiitem_bobfactor, false); + DrawCrispnessMultiItem(crispy->bobfactor, 265, 105, multiitem_bobfactor, false); // Weapon attack alignment - DrawCrispnessMultiItem(crispy->centerweapon, 245, 125, multiitem_centerweapon, + DrawCrispnessMultiItem(crispy->centerweapon, 245, 115, multiitem_centerweapon, crispy->bobfactor == BOBFACTOR_OFF); // Default difficulty - DrawCrispnessMultiItem(crispy->defaultskill, 200, 135, multiitem_difficulties, false); + DrawCrispnessMultiItem(crispy->defaultskill, 200, 125, multiitem_difficulties, false); } diff --git a/src/heretic/r_data.c b/src/heretic/r_data.c index 578137a7e..ed707a3f7 100644 --- a/src/heretic/r_data.c +++ b/src/heretic/r_data.c @@ -874,6 +874,13 @@ void R_InitData(void) R_InitColormaps(); // [crispy] Initialize color translation and color string tables. R_InitHSVColors(); +#ifdef CRISPY_TRUECOLOR + // [crispy] Initialize blending maps for tablified + // overlay translucency (normal and "alt"), used by TrueColor renderer. + R_InitBlendMaps(heretic); + // [crispy] Set pointers to blending functions. + R_InitBlendQuality(); +#endif } diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c index 7f27a052b..90f59a6a3 100644 --- a/src/hexen/h2_main.c +++ b/src/hexen/h2_main.c @@ -211,6 +211,7 @@ void D_BindVariables(void) M_BindIntVariable("crispy_soundmono", &crispy->soundmono); #ifdef CRISPY_TRUECOLOR M_BindIntVariable("crispy_truecolor", &crispy->truecolor); + M_BindIntVariable("crispy_truecolorblend", &crispy->truecolorblend); #endif M_BindIntVariable("crispy_smoothlight", &crispy->smoothlight); M_BindIntVariable("crispy_smoothscaling", &crispy->smoothscaling); diff --git a/src/hexen/mn_menu.c b/src/hexen/mn_menu.c index e09a0b929..522e76432 100644 --- a/src/hexen/mn_menu.c +++ b/src/hexen/mn_menu.c @@ -137,6 +137,9 @@ static void CrispyUncapped(int option); static void CrispyFpsLimit(int option); static void CrispyVsync(int option); static void CrispyBrightmaps(int option); +#ifdef CRISPY_TRUECOLOR +static void CrispyToggleTrueColorBlend(int option); +#endif static void CrispySmoothLighting(int option); static void CrispySoundMono(int option); static void CrispySndChannels(int option); @@ -362,6 +365,12 @@ static int crispnessmenupage; #define NUM_CRISPNESS_MENUS 2 +#ifndef CRISPY_TRUECOLOR +#define NUMCRISPNESS1ITEMS 14 +#else +#define NUMCRISPNESS1ITEMS 15 +#endif + static MenuItem_t Crispness1Items[] = { {ITT_LRFUNC2, "HIGH RESOLUTION RENDERING:", CrispyHires, 0, MENU_NONE}, {ITT_LRFUNC2, "ASPECT RATIO:", CrispyToggleWidescreen, 0, MENU_NONE}, @@ -370,11 +379,12 @@ static MenuItem_t Crispness1Items[] = { {ITT_NUMFUNC, "FRAMERATE LIMIT:", CrispyFpsLimit, 0, MENU_NONE}, {ITT_LRFUNC2, "ENABLE VSYNC:", CrispyVsync, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "BRIGHTMAPS:", CrispyBrightmaps, 0, MENU_NONE}, +#ifdef CRISPY_TRUECOLOR + {ITT_LRFUNC2,"TRANSLUCENCY MODE:", CrispyToggleTrueColorBlend, 0, MENU_NONE}, +#endif {ITT_LRFUNC2, "SMOOTH DIMINISHING LIGHTING:", CrispySmoothLighting, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "MONO SFX:", CrispySoundMono, 0, MENU_NONE}, {ITT_LRFUNC2, "SOUND CHANNELS:", CrispySndChannels, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, @@ -384,7 +394,7 @@ static MenuItem_t Crispness1Items[] = { static Menu_t Crispness1Menu = { 68, 35, DrawCrispnessMenu, - 16, Crispness1Items, + NUMCRISPNESS1ITEMS, Crispness1Items, 0, MENU_OPTIONS }; @@ -392,7 +402,6 @@ static Menu_t Crispness1Menu = { static MenuItem_t Crispness2Items[] = { {ITT_LRFUNC2, "SHOW PLAYER COORDS:", CrispyPlayerCoords, 0, MENU_NONE}, {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, {ITT_LRFUNC2, "FREELOOK MODE:", CrispyFreelook, 0, MENU_NONE}, {ITT_LRFUNC2, "PERMANENT MOUSELOOK:", CrispyMouselook, 0, MENU_NONE}, {ITT_LRFUNC2, "PLAYER VIEW/WEAPON BOBBING:", CrispyBobfactor, 0, MENU_NONE}, @@ -405,7 +414,7 @@ static MenuItem_t Crispness2Items[] = { static Menu_t Crispness2Menu = { 68, 35, DrawCrispnessMenu, - 10, Crispness2Items, + 9, Crispness2Items, 0, MENU_OPTIONS }; @@ -442,6 +451,14 @@ static const multiitem_t multiitem_centerweapon[NUM_CENTERWEAPON] = {CENTERWEAPON_BOB, "BOBBING"}, }; +#ifdef CRISPY_TRUECOLOR +static const multiitem_t multiitem_truecolorblend[NUM_TRUECOLORBLEND] = +{ + {TRUECOLORBLEND_OFF, "SPEED"}, + {TRUECOLORBLEND_ON, "QUALITY"}, +}; +#endif + static const multiitem_t multiitem_widescreen[NUM_RATIOS] = { {RATIO_ORIG, "ORIGINAL"}, @@ -1734,6 +1751,16 @@ static void CrispyBrightmaps(int option) ChangeSettingEnum(&crispy->brightmaps, option, NUM_BRIGHTMAPS); } +#ifdef CRISPY_TRUECOLOR +static void CrispyToggleTrueColorBlend(int option) +{ + crispy->truecolorblend = !crispy->truecolorblend; + + // [crispy] re-set pointers to blending functions + R_InitBlendQuality(); +} +#endif + static void CrispySmoothLightingHook (void) { crispy->smoothlight = !crispy->smoothlight; @@ -2968,6 +2995,8 @@ static void DrawCrispnessNumericItem(int item, int x, int y, const char *zero, static void DrawCrispness1(void) { + int y_shift = 0; + DrawCrispnessHeader("CRISPNESS 1/2"); DrawCrispnessSubheader("RENDERING", 25); @@ -2990,21 +3019,27 @@ static void DrawCrispness1(void) // Vsync DrawCrispnessItem(crispy->vsync, 167, 85); - DrawCrispnessSubheader("VISUAL", 105); + DrawCrispnessSubheader("VISUAL", 95); // Brightmaps - DrawCrispnessMultiItem(crispy->brightmaps, 150, 115, multiitem_brightmaps, false); + DrawCrispnessMultiItem(crispy->brightmaps, 150, 105, multiitem_brightmaps, false); + +#ifdef CRISPY_TRUECOLOR + y_shift += 10; + // Translucency mode + DrawCrispnessMultiItem(crispy->truecolorblend, 205, 115, multiitem_truecolorblend, false); +#endif // Smooth Diminishing Lighting - DrawCrispnessItem(crispy->smoothlight, 257, 125); + DrawCrispnessItem(crispy->smoothlight, 257, 115 + y_shift); - DrawCrispnessSubheader("AUDIBLE", 145); + DrawCrispnessSubheader("AUDIBLE", 125 + y_shift); // Mono SFX - DrawCrispnessItem(crispy->soundmono, 137, 155); + DrawCrispnessItem(crispy->soundmono, 137, 135 + y_shift); // Sound Channels - DrawCrispnessMultiItem(snd_Channels >> 4, 181, 165, multiitem_sndchannels, false); + DrawCrispnessMultiItem(snd_Channels >> 4, 181, 145 + y_shift, multiitem_sndchannels, false); } static void DrawCrispness2(void) @@ -3016,21 +3051,21 @@ static void DrawCrispness2(void) // Player coordinates DrawCrispnessMultiItem(crispy->playercoords, 211, 35, multiitem_widgets, false); - DrawCrispnessSubheader("TACTICAL", 55); + DrawCrispnessSubheader("TACTICAL", 45); // Freelook - DrawCrispnessMultiItem(crispy->freelook_hh, 175, 65, multiitem_freelook_hh, false); + DrawCrispnessMultiItem(crispy->freelook_hh, 175, 55, multiitem_freelook_hh, false); // Mouselook - DrawCrispnessItem(crispy->mouselook, 220, 75); + DrawCrispnessItem(crispy->mouselook, 220, 65); // Bobfactor - DrawCrispnessMultiItem(crispy->bobfactor, 265, 85, multiitem_bobfactor, false); + DrawCrispnessMultiItem(crispy->bobfactor, 265, 75, multiitem_bobfactor, false); // Weapon attack alignment - DrawCrispnessMultiItem(crispy->centerweapon, 245, 95, multiitem_centerweapon, + DrawCrispnessMultiItem(crispy->centerweapon, 245, 85, multiitem_centerweapon, crispy->bobfactor == BOBFACTOR_OFF); // Default difficulty - DrawCrispnessMultiItem(crispy->defaultskill, 200, 105, multiitem_difficulties, false); + DrawCrispnessMultiItem(crispy->defaultskill, 200, 95, multiitem_difficulties, false); } diff --git a/src/hexen/r_data.c b/src/hexen/r_data.c index 29d22415a..8a5682f91 100644 --- a/src/hexen/r_data.c +++ b/src/hexen/r_data.c @@ -811,6 +811,13 @@ void R_InitData(void) #endif // [crispy] initialize color translation and color string tables R_InitHSVColors(); +#ifdef CRISPY_TRUECOLOR + // [crispy] Initialize blending maps for tablified overlay + // translucency (normal and "alt"), used by TrueColor renderer. + R_InitBlendMaps(hexen); + // [crispy] Set pointers to blending functions. + R_InitBlendQuality(); +#endif } //============================================================================= diff --git a/src/i_truecolor.c b/src/i_truecolor.c index fb315b9f5..49c0ea758 100644 --- a/src/i_truecolor.c +++ b/src/i_truecolor.c @@ -37,6 +37,104 @@ typedef union }; } tcpixel_t; +// [crispy] LUTs to store precomputed values for all possible 512x512 color combinations +static uint32_t blendOverLUT[512][512]; // Overlay blending +static uint32_t blendAltLUT[512][512]; // Additive blending (Doom), Overlay "alt" blending + +const uint32_t (*I_BlendAddFunc) (const uint32_t bg_i, const uint32_t fg_i); +const uint32_t (*I_BlendOverFunc) (const uint32_t bg_i, const uint32_t fg_i, const int amount); +const uint32_t (*I_BlendOverAltFunc) (const uint32_t bg_i, const uint32_t fg_i, const int amount); + +// [crispy] Different blending alpha values for different games +#define OVERLAY_ALPHA_TRANMAP 0xA8 // Doom: TRANMAP, 168 (66% opacity) +#define OVERLAY_ALPHA_TINTTAB 0x60 // Raven: TINTTAB, 96 (38% opacity) +#define OVERLAY_ALPHA_TINTTABALT 0x8E // Raven: TINTTAB, 142 (56% opacity, "Alt") +#define OVERLAY_ALPHA_XLATAB 0xC0 // Strife: XLATAB, 192 (75% opacity) +#define OVERLAY_ALPHA_XLATABALT 0x40 // Strife: XLATAB, 64 (25% opacity, "Alt") + + +// [crispy] Initialize blending maps for tablified additive and overlay translucency +void R_InitBlendMaps (GameMission_t mission) +{ + tcpixel_t bg, fg; + tcpixel_t retAdd, retOver; + uint8_t overlay_alpha, overlay_alt_alpha; + + // Define different alpha values for different games + switch (mission) + { + default: // Doom and derivatives + { + overlay_alpha = OVERLAY_ALPHA_TRANMAP; + overlay_alt_alpha = 0; // use additive blending instead of "alt" + break; + } + + case heretic: + case hexen: + { + overlay_alpha = OVERLAY_ALPHA_TINTTAB; + overlay_alt_alpha = OVERLAY_ALPHA_TINTTABALT; + break; + } + + case strife: + { + overlay_alpha = OVERLAY_ALPHA_XLATAB; + overlay_alt_alpha = OVERLAY_ALPHA_XLATABALT; + break; + } + } + + // Shortcut: these variables are always same in tablified approach + retAdd.a = 0xFFU; + retOver.a = 0xFFU; + + for (int bg_index = 0; bg_index < 512; ++bg_index) + { + for (int fg_index = 0; fg_index < 512; ++fg_index) + { + // Convert LUT indices back to RGB values with reduced bit depth + bg.r = (bg_index >> 6) << 5; + bg.g = ((bg_index >> 3) & 0x07) << 5; + bg.b = (bg_index & 0x07) << 5; + + fg.r = (fg_index >> 6) << 5; + fg.g = ((fg_index >> 3) & 0x07) << 5; + fg.b = (fg_index & 0x07) << 5; + + // Overlay blending calculation + retOver.r = (overlay_alpha * fg.r + (0xFFU - overlay_alpha) * bg.r) >> 8; + retOver.g = (overlay_alpha * fg.g + (0xFFU - overlay_alpha) * bg.g) >> 8; + retOver.b = (overlay_alpha * fg.b + (0xFFU - overlay_alpha) * bg.b) >> 8; + blendOverLUT[bg_index][fg_index] = retOver.i; + + if (overlay_alt_alpha == 0) + { + // Additive blending calculation + retAdd.r = MIN(bg.r + fg.r, 0xFFU); + retAdd.g = MIN(bg.g + fg.g, 0xFFU); + retAdd.b = MIN(bg.b + fg.b, 0xFFU); + blendAltLUT[bg_index][fg_index] = retAdd.i; + } + else + { + // Overlay "alt" blending calculation + retOver.r = (overlay_alt_alpha * fg.r + (0xFFU - overlay_alt_alpha) * bg.r) >> 8; + retOver.g = (overlay_alt_alpha * fg.g + (0xFFU - overlay_alt_alpha) * bg.g) >> 8; + retOver.b = (overlay_alt_alpha * fg.b + (0xFFU - overlay_alt_alpha) * bg.b) >> 8; + blendAltLUT[bg_index][fg_index] = retOver.i; + } + } + } +} + +// [crispy] Helper function to convert a pixel color to a LUT index +static inline uint16_t PixelToLUTIndex (const tcpixel_t color) +{ + return ((color.r & 0xE0) << 1) | ((color.g & 0xE0) >> 2) | (color.b >> 5); +} + const uint32_t I_BlendAdd (const uint32_t bg_i, const uint32_t fg_i) { tcpixel_t bg, fg, ret; @@ -52,6 +150,20 @@ const uint32_t I_BlendAdd (const uint32_t bg_i, const uint32_t fg_i) return ret.i; } +const uint32_t I_BlendAddLow (const uint32_t bg_i, const uint32_t fg_i) +{ + tcpixel_t bg, fg; + uint16_t bg_index, fg_index; + + bg.i = bg_i; + fg.i = fg_i; + + bg_index = PixelToLUTIndex(bg); + fg_index = PixelToLUTIndex(fg); + + return blendAltLUT[bg_index][fg_index]; +} + const uint32_t I_BlendDark (const uint32_t bg_i, const int d) { tcpixel_t bg, ret; @@ -81,34 +193,79 @@ const uint32_t I_BlendOver (const uint32_t bg_i, const uint32_t fg_i, const int return ret.i; } +const uint32_t I_BlendOverLow (const uint32_t bg_i, const uint32_t fg_i, const int amount) +{ + tcpixel_t bg, fg; + uint16_t bg_index, fg_index; + + bg.i = bg_i; + fg.i = fg_i; + + bg_index = PixelToLUTIndex(bg); + fg_index = PixelToLUTIndex(fg); + + return blendOverLUT[bg_index][fg_index]; +} + +const uint32_t I_BlendOverAltLow (const uint32_t bg_i, const uint32_t fg_i, const int amount) +{ + tcpixel_t bg, fg; + uint16_t bg_index, fg_index; + + bg.i = bg_i; + fg.i = fg_i; + + bg_index = PixelToLUTIndex(bg); + fg_index = PixelToLUTIndex(fg); + + return blendAltLUT[bg_index][fg_index]; +} + // [crispy] TRANMAP blending emulation, used for Doom const uint32_t I_BlendOverTranmap (const uint32_t bg, const uint32_t fg) { - return I_BlendOver(bg, fg, 0xA8); // 168 (66% opacity) + return I_BlendOverFunc(bg, fg, OVERLAY_ALPHA_TRANMAP); } // [crispy] TINTTAB blending emulation, used for Heretic and Hexen const uint32_t I_BlendOverTinttab (const uint32_t bg, const uint32_t fg) { - return I_BlendOver(bg, fg, 0x60); // 96 (38% opacity) + return I_BlendOverFunc(bg, fg, OVERLAY_ALPHA_TINTTAB); } // [crispy] More opaque ("Alt") TINTTAB blending emulation, used for Hexen's MF_ALTSHADOW drawing const uint32_t I_BlendOverAltTinttab (const uint32_t bg, const uint32_t fg) { - return I_BlendOver(bg, fg, 0x8E); // 142 (56% opacity) + return I_BlendOverAltFunc(bg, fg, OVERLAY_ALPHA_TINTTABALT); } // [crispy] More opaque XLATAB blending emulation, used for Strife const uint32_t I_BlendOverXlatab (const uint32_t bg, const uint32_t fg) { - return I_BlendOver(bg, fg, 0xC0); // 192 (75% opacity) + return I_BlendOverFunc(bg, fg, OVERLAY_ALPHA_XLATAB); } // [crispy] Less opaque ("Alt") XLATAB blending emulation, used for Strife const uint32_t I_BlendOverAltXlatab (const uint32_t bg, const uint32_t fg) { - return I_BlendOver(bg, fg, 0x40); // 64 (25% opacity) + return I_BlendOverAltFunc(bg, fg, OVERLAY_ALPHA_XLATABALT); +} + +// [crispy] Set pointers to blending functions +void R_InitBlendQuality (void) +{ + if (crispy->truecolorblend) + { + I_BlendAddFunc = I_BlendAdd; + I_BlendOverFunc = I_BlendOver; + I_BlendOverAltFunc = I_BlendOver; // Calculate dynamically with given alpha value + } + else + { + I_BlendAddFunc = I_BlendAddLow; + I_BlendOverFunc = I_BlendOverLow; + I_BlendOverAltFunc = I_BlendOverAltLow; // Use precomputed LUT + } } #endif diff --git a/src/i_truecolor.h b/src/i_truecolor.h index a7d0194f3..b90da467c 100644 --- a/src/i_truecolor.h +++ b/src/i_truecolor.h @@ -25,9 +25,15 @@ #ifdef CRISPY_TRUECOLOR #include +#include "d_mode.h" // GameMission_t extern const uint32_t (*blendfunc) (const uint32_t fg, const uint32_t bg); +extern void R_InitBlendMaps (GameMission_t mission); +extern void R_InitBlendQuality (void); +extern const uint32_t (*I_BlendAddFunc) (const uint32_t bg_i, const uint32_t fg_i); +extern const uint32_t (*I_BlendOverFunc) (const uint32_t bg_i, const uint32_t fg_i, const int amount); + const uint32_t I_BlendAdd (const uint32_t bg_i, const uint32_t fg_i); const uint32_t I_BlendDark (const uint32_t bg_i, const int d); const uint32_t I_BlendOver (const uint32_t bg_i, const uint32_t fg_i, const int amount); diff --git a/src/m_config.c b/src/m_config.c index 1bdff289b..0c0bcb2ad 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -2606,6 +2606,14 @@ static default_t extra_defaults_list[] = // CONFIG_VARIABLE_INT(crispy_truecolor), + + //! + // @game doom heretic hexen strife + // + // Quality of translucency in true-color rendering. + // + + CONFIG_VARIABLE_INT(crispy_truecolorblend), #endif //! diff --git a/src/setup/compatibility.c b/src/setup/compatibility.c index d8a2d3a64..6035c0fad 100644 --- a/src/setup/compatibility.c +++ b/src/setup/compatibility.c @@ -91,6 +91,7 @@ void BindCompatibilityVariables(void) M_BindIntVariable("crispy_translucency", &crispy->translucency); #ifdef CRISPY_TRUECOLOR M_BindIntVariable("crispy_truecolor", &crispy->truecolor); + M_BindIntVariable("crispy_truecolorblend", &crispy->truecolorblend); #endif M_BindIntVariable("crispy_uncapped", &crispy->uncapped); M_BindIntVariable("crispy_vsync", &crispy->vsync); diff --git a/src/strife/d_main.c b/src/strife/d_main.c index a053290b0..c2389fa45 100644 --- a/src/strife/d_main.c +++ b/src/strife/d_main.c @@ -550,6 +550,7 @@ void D_BindVariables(void) M_BindIntVariable("crispy_soundmono", &crispy->soundmono); #ifdef CRISPY_TRUECOLOR M_BindIntVariable("crispy_truecolor", &crispy->truecolor); + M_BindIntVariable("crispy_truecolorblend", &crispy->truecolorblend); #endif M_BindIntVariable("crispy_uncapped", &crispy->uncapped); M_BindIntVariable("crispy_vsync", &crispy->vsync); diff --git a/src/strife/r_data.c b/src/strife/r_data.c index 73723cde3..2ab68ffb0 100644 --- a/src/strife/r_data.c +++ b/src/strife/r_data.c @@ -852,6 +852,13 @@ void R_InitData (void) // R_InitColormaps (); // [crispy] Initialize color translation and color string tables. R_InitHSVColors (); +#ifdef CRISPY_TRUECOLOR + // [crispy] Initialize blending maps for tablified overlay + // translucency (normal and "alt"), used by TrueColor renderer. + R_InitBlendMaps(strife); + // [crispy] Set pointers to blending functions. + R_InitBlendQuality(); +#endif }