diff --git a/src/mn_setup.c b/src/mn_setup.c index 472f0bbfb..d7dd3c93d 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -330,6 +330,7 @@ enum str_overlay, str_automap_preset, str_automap_keyed_door, + str_fuzzmode, str_weapon_slots_activation, str_weapon_slots_selection, str_weapon_slots, @@ -3239,6 +3240,10 @@ static const char *exit_sequence_strings[] = { "Off", "Sound Only", "PWAD ENDOOM", "Full" }; +static const char *fuzzmode_strings[] = { + "Vanilla", "Refraction", "Shadow" +}; + static setup_menu_t gen_settings5[] = { {"Smooth Pixel Scaling", S_ONOFF, OFF_CNTR_X, M_SPC, {"smooth_scaling"}, @@ -3250,6 +3255,9 @@ static setup_menu_t gen_settings5[] = { {"Translucency Filter", S_NUM | S_ACTION | S_PCT, OFF_CNTR_X, M_SPC, {"tran_filter_pct"}, .action = MN_Trans}, + {"Partial Invisibility", S_CHOICE | S_STRICT, OFF_CNTR_X, M_SPC, {"fuzzmode"}, + .strings_id = str_fuzzmode, .action = R_SetFuzzColumnMode}, + MI_GAP, {"Voxels", S_ONOFF | S_STRICT, OFF_CNTR_X, M_SPC, {"voxels_rendering"}}, @@ -4788,6 +4796,7 @@ static const char **selectstrings[] = { overlay_strings, automap_preset_strings, automap_keyed_door_strings, + fuzzmode_strings, weapon_slots_activation_strings, weapon_slots_selection_strings, NULL, // str_weapon_slots diff --git a/src/r_draw.c b/src/r_draw.c index 6cc2f019b..4367e1338 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -339,7 +339,7 @@ static const int fuzzoffset[FUZZTABLE] = FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF, FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF, FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF -}; +}; static int fuzzpos = 0; @@ -370,7 +370,7 @@ void R_SetFuzzPosDraw(void) // i.e. spectres and invisible players. // -static void R_DrawFuzzColumn_orig(void) +static void DrawFuzzColumnOriginal(void) { boolean cutoff = false; @@ -448,7 +448,7 @@ static void R_DrawFuzzColumn_orig(void) static int fuzzblocksize; -static void R_DrawFuzzColumn_block(void) +static void DrawFuzzColumnBlocky(void) { boolean cutoff = false; @@ -526,21 +526,185 @@ static void R_DrawFuzzColumn_block(void) } } -// [FG] spectre drawing mode: 0 original, 1 blocky (hires) +#define FUZZDARK 6 * 256 +#define FUZZPAL 256 -boolean fuzzcolumn_mode; -void (*R_DrawFuzzColumn)(void) = R_DrawFuzzColumn_orig; +static const int fuzzdark[FUZZTABLE] = +{ + 4 * FUZZPAL,0,6 * FUZZPAL,0,6 * FUZZPAL,6 * FUZZPAL,0, + 6 * FUZZPAL,6 * FUZZPAL,0,6 * FUZZPAL,6 * FUZZPAL,6 * FUZZPAL,0, + 6 * FUZZPAL,8 * FUZZPAL,6 * FUZZPAL,0,0,0,0, + 4 * FUZZPAL,0,0,6 * FUZZPAL,6 * FUZZPAL,6 * FUZZPAL,6 * FUZZPAL,0, + 4 * FUZZPAL,0,6 * FUZZPAL,6 * FUZZPAL,0,0,6 * FUZZPAL, + 6 * FUZZPAL,0,0,0,0,6 * FUZZPAL,6 * FUZZPAL, + 6 * FUZZPAL,6 * FUZZPAL,0,6 * FUZZPAL,6 * FUZZPAL,0,6 * FUZZPAL, +}; + +static void DrawFuzzColumnRefraction(void) +{ + boolean cutoff = false; -void R_SetFuzzColumnMode(void) + if (dc_x % fuzzblocksize) + { + return; + } + + if (!dc_yl) + { + dc_yl = 1; + } + + if (dc_yh == viewheight - 1) + { + dc_yh = viewheight - 2; + cutoff = true; + } + + int count = dc_yh - dc_yl; + + if (count < 0) + { + return; + } + +#ifdef RANGECHECK + if ((unsigned)dc_x >= video.width || dc_yl < 0 || dc_yh >= video.height) + { + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } +#endif + + ++count; + + byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + + int lines = fuzzblocksize - (dc_yl % fuzzblocksize); + + int dark = FUZZDARK; + int offset = 0; + + do + { + count -= lines; + + // if (count < 0) + // { + // lines += count; + // count = 0; + // } + const int mask = count >> (8 * sizeof(mask) - 1); + lines += count & mask; + count &= ~mask; + + const byte fuzz = fullcolormap[dark + dest[linesize * offset]]; + + do + { + memset(dest, fuzz, fuzzblocksize); + dest += linesize; + } while (--lines); + + ++fuzzpos; + + // Clamp table lookup index. + fuzzpos &= (fuzzpos - FUZZTABLE) >> (8 * sizeof(fuzzpos) - 1); // killough 1/99 + + dark = fuzzdark[fuzzpos]; + offset = fuzzoffset[fuzzpos]; + + lines = fuzzblocksize; + } while (count); + + if (cutoff) + { + const byte fuzz = + fullcolormap[dark + dest[linesize * (offset - FUZZOFF) / 2]]; + memset(dest, fuzz, fuzzblocksize); + } +} + +static void DrawFuzzColumnShadow(void) { - if (fuzzcolumn_mode && current_video_height > SCREENHEIGHT) + boolean cutoff = false; + + // Adjust borders. Low... + if (!dc_yl) { - fuzzblocksize = FixedToInt(video.yscale); - R_DrawFuzzColumn = R_DrawFuzzColumn_block; + dc_yl = 1; } - else + + // .. and high. + if (dc_yh == viewheight - 1) + { + dc_yh = viewheight - 2; + cutoff = true; + } + + int count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + { + return; + } + +#ifdef RANGECHECK + if ((unsigned)dc_x >= video.width || dc_yl < 0 || dc_yh >= video.height) { - R_DrawFuzzColumn = R_DrawFuzzColumn_orig; + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } +#endif + + byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + + count++; // killough 1/99: minor tuning + + do + { + *dest = fullcolormap[8 * 256 + *dest]; + + dest += linesize; // killough 11/98 + + ++fuzzpos; + + // Clamp table lookup index. + fuzzpos &= (fuzzpos - FUZZTABLE) >> (8 * sizeof(fuzzpos) - 1); // killough 1/99 + } while (--count); + + if (cutoff) + { + *dest = fullcolormap[8 * 256 + *dest]; + } +} + +fuzzmode_t fuzzmode; +void (*R_DrawFuzzColumn)(void) = DrawFuzzColumnOriginal; + +void R_SetFuzzColumnMode(void) +{ + fuzzmode_t mode = + strictmode || (netgame && !solonet) ? FUZZ_BLOCKY : fuzzmode; + + switch (mode) + { + case FUZZ_BLOCKY: + if (current_video_height > SCREENHEIGHT) + { + fuzzblocksize = FixedToInt(video.yscale); + R_DrawFuzzColumn = DrawFuzzColumnBlocky; + } + else + { + R_DrawFuzzColumn = DrawFuzzColumnOriginal; + } + break; + case FUZZ_REFRACTION: + fuzzblocksize = FixedToInt(video.yscale); + R_DrawFuzzColumn = DrawFuzzColumnRefraction; + break; + case FUZZ_SHADOW: + R_DrawFuzzColumn = DrawFuzzColumnShadow; + break; } } diff --git a/src/r_draw.h b/src/r_draw.h index 9ee009bd5..3074f6ec7 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -48,7 +48,14 @@ void R_SetFuzzPosTic(void); void R_SetFuzzPosDraw(void); // [FG] spectre drawing mode -extern boolean fuzzcolumn_mode; +typedef enum +{ + FUZZ_BLOCKY, + FUZZ_REFRACTION, + FUZZ_SHADOW, +} fuzzmode_t; + +extern fuzzmode_t fuzzmode; void R_SetFuzzColumnMode(void); void R_DrawSkyColumn(void); diff --git a/src/r_main.c b/src/r_main.c index b5e750072..7efe9e6df 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1041,8 +1041,9 @@ void R_BindRenderVariables(void) M_BindBool("flipcorpses", &flipcorpses, NULL, false, ss_enem, wad_no, "Randomly mirrored death animations"); - M_BindBool("fuzzcolumn_mode", &fuzzcolumn_mode, NULL, true, ss_none, wad_no, - "Fuzz rendering (0 = Resolution-dependent; 1 = Blocky)"); + M_BindNum("fuzzmode", &fuzzmode, NULL, + FUZZ_BLOCKY, FUZZ_BLOCKY, FUZZ_SHADOW, ss_none, wad_no, + "Partial Invisibility (0 = Vanilla; 1 = Refraction; 2 = Shadow)"); BIND_BOOL(draw_nearby_sprites, true, "Draw sprites overlapping into visible sectors");