diff --git a/src/am_map.c b/src/am_map.c index defe3ee48..4a6ddffc4 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1445,10 +1445,10 @@ static void AM_clearFB(int color) { // [Nugget] Minimap: take `f_x` and `f_y` into account int h = f_h; - byte *src = I_VideoBuffer + ((f_y * video.pitch) + f_x); + pixel_t *src = I_VideoBuffer + ((f_y * video.pitch) + f_x); while (h--) { - memset(src, color, f_w); + V_IndexSet(src, color, f_w); src += video.pitch; } } @@ -1601,7 +1601,7 @@ static void PUTDOT(int xx, int yy, int cc) // [Nugget] Minimap: take `f_x` and `f_y` into account if ((f_x <= xx && xx < f_x+f_w) && (f_y <= yy && yy < f_y+f_h)) - I_VideoBuffer[(yy) * video.pitch + (xx)] = (cc); + I_VideoBuffer[(yy) * video.pitch + (xx)] = V_IndexToRGB(cc); } @@ -1697,19 +1697,26 @@ static void AM_putWuDot(int x, int y, int color, int weight) { if (STRICTMODE(flip_levels)) { x = f_x*2 + f_w - 1 - x; } // [Nugget] Flip levels - byte *dest = &I_VideoBuffer[y * video.pitch + x]; - unsigned int *fg2rgb = Col2RGB8[weight]; - unsigned int *bg2rgb = Col2RGB8[64 - weight]; - unsigned int fg, bg; - // [Nugget] Minimap: take `f_x` and `f_y` into account if (!((f_x <= x && x < f_x+f_w) && (f_y <= y && y < f_y+f_h))) { return; } - fg = fg2rgb[color]; - bg = bg2rgb[*dest]; - fg = (fg + bg) | 0x1f07c1f; - *dest = RGB32k[0][0][fg & (fg >> 15)]; + pixel_t *dest = &I_VideoBuffer[y * video.pitch + x]; + + if (truecolor_rendering) + { + if (weight) { *dest = V_LerpRGB(*dest, V_IndexToRGB(color), weight, 64); } + } + else { + unsigned int *fg2rgb = Col2RGB8[weight]; + unsigned int *bg2rgb = Col2RGB8[64 - weight]; + unsigned int fg, bg; + + fg = fg2rgb[color]; + bg = bg2rgb[V_IndexFromRGB(*dest)]; + fg = (fg + bg) | 0x1f07c1f; + *dest = V_IndexToRGB(RGB32k[0][0][fg & (fg >> 15)]); + } } @@ -2795,7 +2802,17 @@ void AM_shadeScreen(void) for (int y = f_y; y < f_y+f_h; y++) { const int pixel = y * video.pitch + x; - I_VideoBuffer[pixel] = colormaps[0][automap_overlay_darkening * 256 + I_VideoBuffer[pixel]]; + + if (truecolor_rendering) + { + I_VideoBuffer[pixel] = V_ShadeRGB(I_VideoBuffer[pixel], automap_overlay_darkening, 32); + } + else + { + I_VideoBuffer[pixel] = V_IndexToRGB( + colormaps[0][automap_overlay_darkening * 256 + V_IndexFromRGB(I_VideoBuffer[pixel])] + ); + } } } } diff --git a/src/doomtype.h b/src/doomtype.h index eebd266f6..f75ee129c 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -35,7 +35,7 @@ typedef enum {false, true} boolean; typedef uint8_t byte; -typedef byte pixel_t; +typedef uint32_t pixel_t; // This could be wider for >8 bit display. Indeed, true color support is // posibble precalculating 24bpp lightmap/colormap LUT. from darkening PLAYPAL diff --git a/src/f_wipe.c b/src/f_wipe.c index 08a994a59..81d72ca96 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -48,9 +48,9 @@ static int wipe_columns; // SCREEN WIPE PACKAGE // -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; // [FG] cross-fading screen wipe implementation @@ -76,20 +76,26 @@ static int wipe_doColorXForm(int width, int height, int ticks) for (int y = 0; y < height; y++) { - byte *sta = wipe_scr_start + y * width; - byte *end = wipe_scr_end + y * width; - byte *dst = wipe_scr + y * video.pitch; + pixel_t *sta = wipe_scr_start + y * width; + pixel_t *end = wipe_scr_end + y * width; + pixel_t *dst = wipe_scr + y * video.pitch; for (int x = 0; x < width; x++) { - unsigned int *fg2rgb = Col2RGB8[fade_tick]; - unsigned int *bg2rgb = Col2RGB8[64 - fade_tick]; - unsigned int fg, bg; - - fg = fg2rgb[end[x]]; - bg = bg2rgb[sta[x]]; - fg = (fg + bg) | 0x1f07c1f; - dst[x] = RGB32k[0][0][fg & (fg >> 15)]; + if (truecolor_rendering) + { + if (fade_tick) { dst[x] = V_LerpRGB(sta[x], end[x], fade_tick, 64); } + } + else { + unsigned int *fg2rgb = Col2RGB8[fade_tick]; + unsigned int *bg2rgb = Col2RGB8[64 - fade_tick]; + unsigned int fg, bg; + + fg = fg2rgb[V_IndexFromRGB(end[x])]; + bg = bg2rgb[V_IndexFromRGB(sta[x])]; + fg = (fg + bg) | 0x1f07c1f; + dst[x] = V_IndexToRGB(RGB32k[0][0][fg & (fg >> 15)]); + } } } @@ -417,12 +423,12 @@ static int wipe_doFizzle(int width, int height, int ticks) vrect_t rect = {x, y, 1, 1}; V_ScaleRect(&rect); - byte *src = wipe_scr_end + rect.sy * width + rect.sx; - byte *dest = wipe_scr + rect.sy * video.pitch + rect.sx; + pixel_t *src = wipe_scr_end + rect.sy * width + rect.sx; + pixel_t *dest = wipe_scr + rect.sy * video.pitch + rect.sx; while (rect.sh--) { - memcpy(dest, src, rect.sw); + V_RGBCopy(dest, src, rect.sw); src += width; dest += video.pitch; } diff --git a/src/i_video.c b/src/i_video.c index 530f7691e..7b627071a 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -99,10 +99,12 @@ static boolean disk_icon; // killough 10/98 // [Nugget] /----------------------------------------------------------------- +truecolormode_t truecolor_rendering; + static const char *sdl_renderdriver = ""; -static int red_intensity, green_intensity, blue_intensity; -static int color_saturation, color_contrast; +int red_intensity, green_intensity, blue_intensity; +int color_saturation, color_contrast; // [Nugget] -----------------------------------------------------------------/ @@ -897,7 +899,7 @@ void I_FinishUpdate(void) // I_ReadScreen // -void I_ReadScreen(byte *dst) +void I_ReadScreen(pixel_t *dst) { V_GetBlock(0, 0, video.width, video.height, dst); } @@ -997,36 +999,10 @@ static void I_RestoreDiskBackground(void) int gamma2; -// [Nugget]: -// [JN] Saturation percent array. -// 0.66 = 0% saturation, 0.0 = 100% saturation. -const float I_SaturationPercent[101] = -{ - 0.660000f, 0.653400f, 0.646800f, 0.640200f, 0.633600f, - 0.627000f, 0.620400f, 0.613800f, 0.607200f, 0.600600f, - 0.594000f, 0.587400f, 0.580800f, 0.574200f, 0.567600f, - 0.561000f, 0.554400f, 0.547800f, 0.541200f, 0.534600f, - 0.528000f, 0.521400f, 0.514800f, 0.508200f, 0.501600f, - 0.495000f, 0.488400f, 0.481800f, 0.475200f, 0.468600f, - 0.462000f, 0.455400f, 0.448800f, 0.442200f, 0.435600f, - 0.429000f, 0.422400f, 0.415800f, 0.409200f, 0.402600f, - 0.396000f, 0.389400f, 0.382800f, 0.376200f, 0.369600f, - 0.363000f, 0.356400f, 0.349800f, 0.343200f, 0.336600f, - 0.330000f, 0.323400f, 0.316800f, 0.310200f, 0.303600f, - 0.297000f, 0.290400f, 0.283800f, 0.277200f, 0.270600f, - 0.264000f, 0.257400f, 0.250800f, 0.244200f, 0.237600f, - 0.231000f, 0.224400f, 0.217800f, 0.211200f, 0.204600f, - 0.198000f, 0.191400f, 0.184800f, 0.178200f, 0.171600f, - 0.165000f, 0.158400f, 0.151800f, 0.145200f, 0.138600f, - 0.132000f, 0.125400f, 0.118800f, 0.112200f, 0.105600f, - 0.099000f, 0.092400f, 0.085800f, 0.079200f, 0.072600f, - 0.066000f, 0.059400f, 0.052800f, 0.046200f, 0.039600f, - 0.033000f, 0.026400f, 0.019800f, 0.013200f, 0, - 0 -}; - void I_SetPalette(byte *palette) { + #if 0 + // haleyjd int i; const byte *const gamma = gammatable[gamma2]; @@ -1080,11 +1056,18 @@ void I_SetPalette(byte *palette) SDL_SetPaletteColors(screenbuffer->format->palette, colors, 0, 256); + #endif + + V_InitPalsColors(); + if (vga_porch_flash) { // "flash" the pillars/letterboxes with palette changes, // emulating VGA "porch" behaviour - SDL_SetRenderDrawColor(renderer, colors[0].r, colors[0].g, colors[0].b, + SDL_SetRenderDrawColor(renderer, + V_RedFromRGB(palscolors[0][0]), + V_GreenFromRGB(palscolors[0][0]), + V_BlueFromRGB(palscolors[0][0]), SDL_ALPHA_OPAQUE); } } @@ -1851,7 +1834,8 @@ static void CreateSurfaces(int w, int h) SDL_FreeSurface(screenbuffer); } - screenbuffer = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0); + screenbuffer = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB8888); + SDL_SetSurfaceBlendMode(screenbuffer, SDL_BLENDMODE_NONE); SDL_FillRect(screenbuffer, NULL, 0); I_VideoBuffer = screenbuffer->pixels; @@ -1975,6 +1959,11 @@ void I_InitGraphics(void) void I_BindVideoVariables(void) { + // [Nugget] True color + BIND_NUM_GENERAL(truecolor_rendering, + TRUECOLOR_OFF, TRUECOLOR_OFF, NUM_TRUECOLOR_MODES-1, + "True-color rendering (0 = Off; 1 = Hybrid; 2 = Full"); + M_BindNum("current_video_height", &default_current_video_height, ¤t_video_height, 600, 200, UL, ss_none, wad_no, "Vertical resolution"); diff --git a/src/i_video.h b/src/i_video.h index 2e4e4ceef..11dafe25d 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -60,7 +60,7 @@ void I_SetPalette(byte *palette); void I_FinishUpdate(void); -void I_ReadScreen(byte *dst); +void I_ReadScreen(pixel_t *dst); void I_ResetScreen(void); // killough 10/98 void I_ToggleVsync(void); // [JN] Calls native SDL vsync toggle @@ -81,10 +81,26 @@ extern boolean toggle_exclusive_fullscreen; extern boolean correct_aspect_ratio; extern boolean screenvisible; -// [Nugget] +// [Nugget] /----------------------------------------------------------------- + +typedef enum truecolormode_s { + TRUECOLOR_OFF, + TRUECOLOR_HYBRID, + TRUECOLOR_FULL, + + NUM_TRUECOLOR_MODES +} truecolormode_t; + +extern truecolormode_t truecolor_rendering; + +extern int red_intensity, green_intensity, blue_intensity; +extern int color_saturation, color_contrast; + #define GAMMA2MAX 30 extern const float gammalevels[GAMMA2MAX+1]; +// [Nugget] -----------------------------------------------------------------/ + extern int gamma2; byte I_GetNearestColor(byte *palette, int r, int g, int b); diff --git a/src/m_cheat.c b/src/m_cheat.c index f61b835c7..ac4bfcecc 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -63,13 +63,13 @@ // [Nugget] Testing cheat /------------ -//#define NUGMAGIC +#define NUGMAGIC #ifdef NUGMAGIC static void cheat_magic(void) { - + displaymsg("Light %s", (diminished_lighting = !diminished_lighting) ? "ON" : "OFF"); } static void cheat_magic2(void) diff --git a/src/mn_setup.c b/src/mn_setup.c index 2dfc21410..73f7408bf 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -367,6 +367,7 @@ enum // [Nugget] -------------------------------------------------------------- + str_truecolor_mode, str_bobbing_style, str_force_carousel, str_crosshair_lockon, @@ -2669,6 +2670,11 @@ static setup_tab_t gen_tabs[] = { {NULL} }; +// [Nugget] True color +static const char *truecolor_mode_strings[] = { + "Off", "Hybrid", "Full" +}; + static int resolution_scale; static const char **GetResolutionScaleStrings(void) @@ -2803,7 +2809,10 @@ void MN_ResetGamma(void) static setup_menu_t gen_settings1[] = { - // [Nugget] These first three items now report + {"True-color Rendering", S_CHOICE, CNTR_X, M_SPC, {"truecolor_rendering"}, + .strings_id = str_truecolor_mode}, + + // [Nugget] The following three items now report // the current resolution when sitting on them {"Resolution Scale", S_THERMO | S_THRM_SIZE11 | S_ACTION | S_RES, CNTR_X, @@ -5605,6 +5614,7 @@ static const char **selectstrings[] = { // [Nugget] -------------------------------------------------------------- + truecolor_mode_strings, bobbing_style_strings, force_carousel_strings, crosshair_lockon_strings, diff --git a/src/mn_snapshot.c b/src/mn_snapshot.c index c8f1bd841..6ffc184ee 100644 --- a/src/mn_snapshot.c +++ b/src/mn_snapshot.c @@ -31,10 +31,10 @@ static const char snapshot_str[] = "NUGGETDOOM_SNAPSHOT"; static const int snapshot_len = arrlen(snapshot_str); -static const int snapshot_size = SCREENWIDTH * SCREENHEIGHT; +static const int snapshot_size = (SCREENWIDTH * SCREENHEIGHT) * sizeof(pixel_t); -static byte *snapshots[10]; -static byte *current_snapshot; +static pixel_t *snapshots[10]; +static pixel_t *current_snapshot; static char savegametimes[10][32]; const int MN_SnapshotDataSize(void) @@ -132,9 +132,9 @@ static void TakeSnapshot(void) current_snapshot = malloc(snapshot_size * sizeof(**snapshots)); } - byte *p = current_snapshot; + pixel_t *p = current_snapshot; - const byte *s = I_VideoBuffer; + const pixel_t *s = I_VideoBuffer; int x, y; for (y = 0; y < SCREENHEIGHT; y++) @@ -181,11 +181,11 @@ boolean MN_DrawSnapshot(int n, int x, int y, int w, int h) const fixed_t step_x = (SCREENWIDTH << FRACBITS) / rect.sw; const fixed_t step_y = (SCREENHEIGHT << FRACBITS) / rect.sh; - byte *dest = I_VideoBuffer + rect.sy * video.pitch + rect.sx; + pixel_t *dest = I_VideoBuffer + rect.sy * video.pitch + rect.sx; fixed_t srcx, srcy; int destx, desty; - byte *destline, *srcline; + pixel_t *destline, *srcline; for (desty = 0, srcy = 0; desty < rect.sh; desty++, srcy += step_y) { diff --git a/src/r_defs.h b/src/r_defs.h index 5525e59b3..62686b4a9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -388,8 +388,13 @@ typedef struct vissprite_s // andrewj: voxel support int voxel_index; - // [Nugget] + // [Nugget] ---------------------------------------------------------------- + byte *tranmap; + + // True color + short lightindex; + lighttable_t *nextcolormap; } vissprite_t; // diff --git a/src/r_draw.c b/src/r_draw.c index c6db31133..711b161c8 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -54,7 +54,7 @@ int viewwidth; int viewheight; int viewwindowx; int viewwindowy; -static byte **ylookup = NULL; +static pixel_t **ylookup = NULL; static int *columnofs = NULL; static int linesize; // killough 11/98 @@ -81,6 +81,10 @@ int dc_texheight; // killough byte *dc_source; // first pixel in a column (possibly virtual) byte dc_skycolor; +// [Nugget] True color +short dc_lightindex, dc_minlightindex, dc_maxlightindex = 255; +lighttable_t *dc_nextcolormap; + // // A column is a vertical slice/span from a wall texture that, // given the DOOM style restrictions on the view orientation, @@ -112,7 +116,7 @@ byte dc_skycolor; dc_x); \ } \ \ - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; \ + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; \ \ const fixed_t fracstep = dc_iscale; \ fixed_t frac = dc_texturemid + (dc_yl - centery) * fracstep; \ @@ -160,8 +164,35 @@ byte dc_skycolor; } \ } -DRAW_COLUMN(, dc_colormap[0][src]) -DRAW_COLUMN(Brightmap, dc_colormap[dc_brightmap[src]][src]) +DRAW_COLUMN(, + (truecolor_rendering == TRUECOLOR_FULL && !fixedcolormap) + ? V_ShadeRGB( + V_IndexToRGB(src), + dc_maxlightindex - dc_lightindex, + dc_maxlightindex + ) + : (dc_nextcolormap) + ? V_LerpRGB(V_IndexToRGB(dc_colormap[0][src]), + V_IndexToRGB(dc_nextcolormap[src]), + dc_lightindex, + dc_maxlightindex) + : V_IndexToRGB(dc_colormap[0][src]) +) + +DRAW_COLUMN(Brightmap, + (truecolor_rendering == TRUECOLOR_FULL && !fixedcolormap) + ? V_ShadeRGB( + V_IndexToRGB(src), + dc_brightmap[src] ? 0 : dc_maxlightindex - dc_lightindex, + dc_maxlightindex + ) + : (dc_nextcolormap && !dc_brightmap[src]) + ? V_LerpRGB(V_IndexToRGB(dc_colormap[0][src]), + V_IndexToRGB(dc_nextcolormap[src]), + dc_lightindex, + dc_maxlightindex) + : V_IndexToRGB(dc_colormap[dc_brightmap[src]][src]) +) // Here is the version of R_DrawColumn that deals with translucent // phares // textures and sprites. It's identical to R_DrawColumn except // | @@ -176,9 +207,14 @@ DRAW_COLUMN(Brightmap, dc_colormap[dc_brightmap[src]][src]) // actual code differences are. DRAW_COLUMN(TL, - tranmap[(*dest << 8) + dc_colormap[0][src]]) + V_IndexToRGB(tranmap[(V_IndexFromRGB(*dest) << 8) + + dc_colormap[0][src]]) +) + DRAW_COLUMN(TLBrightmap, - tranmap[(*dest << 8) + dc_colormap[dc_brightmap[src]][src]]) + V_IndexToRGB(tranmap[(V_IndexFromRGB(*dest) << 8) + + dc_colormap[dc_brightmap[src]][src]]) +) // // Sky drawing: for showing just a color above the texture @@ -200,7 +236,7 @@ void R_DrawSkyColumn(void) } #endif - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; const fixed_t fracstep = dc_iscale; fixed_t frac = dc_texturemid + (dc_yl - centery) * fracstep; @@ -225,6 +261,7 @@ void R_DrawSkyColumn(void) for (i = 0; i < n; ++i) { *dest = colormap[skycolor]; + *dest = V_IndexToRGB(*dest); dest += linesize; frac += fracstep; } @@ -249,6 +286,7 @@ void R_DrawSkyColumn(void) [(main_tranmap[(colormap[source[0]] << 8) + colormap[skycolor]] << 8) + colormap[skycolor]]; + *dest = V_IndexToRGB(*dest); dest += linesize; frac += fracstep; } @@ -272,6 +310,7 @@ void R_DrawSkyColumn(void) { *dest = main_tranmap[(colormap[source[0]] << 8) + colormap[skycolor]]; + *dest = V_IndexToRGB(*dest); dest += linesize; frac += fracstep; } @@ -297,6 +336,7 @@ void R_DrawSkyColumn(void) do { *dest = colormap[source[frac >> FRACBITS]]; + *dest = V_IndexToRGB(*dest); dest += linesize; // killough 11/98 if ((frac += fracstep) >= heightmask) { @@ -309,15 +349,18 @@ void R_DrawSkyColumn(void) while ((count -= 2) >= 0) // texture height is a power of 2 -- killough { *dest = colormap[source[(frac >> FRACBITS) & heightmask]]; + *dest = V_IndexToRGB(*dest); dest += linesize; // killough 11/98 frac += fracstep; *dest = colormap[source[(frac >> FRACBITS) & heightmask]]; + *dest = V_IndexToRGB(*dest); dest += linesize; // killough 11/98 frac += fracstep; } if (count & 1) { *dest = colormap[source[(frac >> FRACBITS) & heightmask]]; + *dest = V_IndexToRGB(*dest); } } } @@ -406,7 +449,7 @@ static void DrawFuzzColumnOriginal(void) // or blocky mode removed. // Does not work with blocky mode. - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; // Looks like an attempt at dithering, // using the colormap #6 (of 0-31, a bit brighter than average). @@ -426,7 +469,8 @@ static void DrawFuzzColumnOriginal(void) // why_i_left_doom.html *dest = - fullcolormap[6 * 256 + dest[linesize * fuzzoffset[fuzzpos]]]; + fullcolormap[6 * 256 + V_IndexFromRGB(dest[linesize * fuzzoffset[fuzzpos]])]; + *dest = V_IndexToRGB(*dest); dest += linesize; // killough 11/98 ++fuzzpos; @@ -440,7 +484,8 @@ static void DrawFuzzColumnOriginal(void) if (cutoff) { *dest = fullcolormap - [6 * 256 + dest[linesize * (fuzzoffset[fuzzpos] - FUZZOFF) / 2]]; + [6 * 256 + V_IndexFromRGB(dest[linesize * (fuzzoffset[fuzzpos] - FUZZOFF) / 2])]; + *dest = V_IndexToRGB(*dest); } } @@ -484,7 +529,7 @@ static void DrawFuzzColumnBlocky(void) ++count; - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; int lines = fuzzblocksize - (dc_yl % fuzzblocksize); @@ -504,11 +549,11 @@ static void DrawFuzzColumnBlocky(void) count &= ~mask; const byte fuzz = - fullcolormap[6 * 256 + dest[linesize * fuzzoffset[fuzzpos]]]; + fullcolormap[6 * 256 + V_IndexFromRGB(dest[linesize * fuzzoffset[fuzzpos]])]; do { - memset(dest, fuzz, fuzzblockwidth); + V_IndexSet(dest, fuzz, fuzzblockwidth); dest += linesize; } while (--lines); @@ -523,8 +568,8 @@ static void DrawFuzzColumnBlocky(void) if (cutoff) { const byte fuzz = fullcolormap - [6 * 256 + dest[linesize * (fuzzoffset[fuzzpos] - FUZZOFF) / 2]]; - memset(dest, fuzz, fuzzblocksize); + [6 * 256 + V_IndexFromRGB(dest[linesize * (fuzzoffset[fuzzpos] - FUZZOFF) / 2])]; + V_IndexSet(dest, fuzz, fuzzblocksize); } } @@ -578,7 +623,7 @@ static void DrawFuzzColumnRefraction(void) ++count; - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; int lines = fuzzblocksize - (dc_yl % fuzzblocksize); @@ -600,11 +645,11 @@ static void DrawFuzzColumnRefraction(void) lines += count & mask; count &= ~mask; - const byte fuzz = fullcolormap[dark + dest[linesize * offset]]; + const byte fuzz = fullcolormap[dark + V_IndexFromRGB(dest[linesize * offset])]; do { - memset(dest, fuzz, fuzzblockwidth); + V_IndexSet(dest, fuzz, fuzzblockwidth); dest += linesize; } while (--lines); @@ -622,8 +667,8 @@ static void DrawFuzzColumnRefraction(void) if (cutoff) { const byte fuzz = - fullcolormap[dark + dest[linesize * (offset - FUZZOFF) / 2]]; - memset(dest, fuzz, fuzzblocksize); + fullcolormap[dark + V_IndexFromRGB(dest[linesize * (offset - FUZZOFF) / 2])]; + V_IndexSet(dest, fuzz, fuzzblocksize); } } @@ -644,13 +689,13 @@ static void DrawFuzzColumnShadow(void) } #endif - byte *dest = ylookup[dc_yl] + columnofs[dc_x]; + pixel_t *dest = ylookup[dc_yl] + columnofs[dc_x]; count++; // killough 1/99: minor tuning do { - *dest = fullcolormap[8 * 256 + *dest]; + *dest = V_IndexToRGB(fullcolormap[8 * 256 + V_IndexFromRGB(*dest)]); dest += linesize; // killough 11/98 } while (--count); @@ -763,13 +808,17 @@ fixed_t ds_yfrac; fixed_t ds_xstep; fixed_t ds_ystep; +// [Nugget] True color +short ds_lightindex, ds_minlightindex, ds_maxlightindex = 255; +lighttable_t *ds_nextcolormap; + // start of a 64*64 tile image byte *ds_source; #define R_DRAW_SPAN(NAME, SRCPIXEL) \ static void DrawSpan##NAME(void) \ { \ - byte *dest = ylookup[ds_y] + columnofs[ds_x1]; \ + pixel_t *dest = ylookup[ds_y] + columnofs[ds_x1]; \ \ unsigned count = ds_x2 - ds_x1 + 1; \ \ @@ -828,8 +877,35 @@ byte *ds_source; } \ } -R_DRAW_SPAN(, ds_colormap[0][src]) -R_DRAW_SPAN(Brightmap, ds_colormap[ds_brightmap[src]][src]) +R_DRAW_SPAN(, + (truecolor_rendering == TRUECOLOR_FULL && !fixedcolormap) + ? V_ShadeRGB( + V_IndexToRGB(src), + ds_maxlightindex - ds_lightindex, + ds_maxlightindex + ) + : (ds_nextcolormap) + ? V_LerpRGB(V_IndexToRGB(ds_colormap[0][src]), + V_IndexToRGB(ds_nextcolormap[src]), + ds_lightindex, + ds_maxlightindex) + : V_IndexToRGB(ds_colormap[0][src]) +) + +R_DRAW_SPAN(Brightmap, + (truecolor_rendering == TRUECOLOR_FULL && !fixedcolormap) + ? V_ShadeRGB( + V_IndexToRGB(src), + dc_brightmap[src] ? 0 : ds_maxlightindex - ds_lightindex, + ds_maxlightindex + ) + : (ds_nextcolormap && !ds_brightmap[src]) + ? V_LerpRGB(V_IndexToRGB(ds_colormap[0][src]), + V_IndexToRGB(ds_nextcolormap[src]), + ds_lightindex, + ds_maxlightindex) + : V_IndexToRGB(ds_colormap[ds_brightmap[src]][src]) +) void (*R_DrawColumn)(void) = DrawColumn; void (*R_DrawTLColumn)(void) = DrawColumnTL; diff --git a/src/r_draw.h b/src/r_draw.h index 951d18f29..2f5360b03 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -32,6 +32,10 @@ extern fixed_t dc_texturemid; extern int dc_texheight; // killough extern byte dc_skycolor; +// [Nugget] True color +extern short dc_lightindex, dc_minlightindex, dc_maxlightindex; +extern lighttable_t *dc_nextcolormap; + // first pixel in a column extern byte *dc_source; extern const byte *dc_brightmap; @@ -79,6 +83,10 @@ extern fixed_t ds_yfrac; extern fixed_t ds_xstep; extern fixed_t ds_ystep; +// [Nugget] True color +extern short ds_lightindex, ds_minlightindex, ds_maxlightindex; +extern lighttable_t *ds_nextcolormap; + // start of a 64*64 tile image extern byte *ds_source; extern byte *translationtables; diff --git a/src/r_main.c b/src/r_main.c index 3fbe5502b..e9cfa4073 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -854,12 +854,35 @@ void R_SmoothLight(void) P_SegLengths(true); } +// [Nugget] +static int64_t temp_lightindex = 0; + int R_GetLightIndex(fixed_t scale) { - const int index = ((int64_t)scale * (160 << FRACBITS) / lightfocallength) >> LIGHTSCALESHIFT; + // [Nugget] True color: calculate part of `dc_lightindex` here + const int index = (temp_lightindex = (int64_t)scale * (160 << FRACBITS) / lightfocallength) >> LIGHTSCALESHIFT; return BETWEEN(0, MAXLIGHTSCALE - 1, index); } +// [Nugget] True color +byte R_GetLightIndexFrac(void) +{ + #define INDEX_PRECISION 255 + + if (truecolor_rendering == TRUECOLOR_FULL) + { + int64_t temp_lightindex_scaled = temp_lightindex / (MAXLIGHTSCALE * (1 << LIGHTSCALESHIFT) / 32); + + return BETWEEN(0, INDEX_PRECISION, temp_lightindex_scaled); + } + else { + return (temp_lightindex % ((int64_t) 1 << LIGHTSCALESHIFT)) + * INDEX_PRECISION / ((int64_t) 1 << LIGHTSCALESHIFT); + } + + #undef INDEX_PRECISION +} + static fixed_t viewpitch; static void R_SetupFreelook(void) @@ -1782,7 +1805,7 @@ void R_RenderPlayerView (player_t* player) int first_y = ((viewheight % ph) / 2), first_x; - byte *const dest = I_VideoBuffer; + pixel_t *const dest = I_VideoBuffer; for (y = viewwindowy; y < (viewwindowy + viewheight);) { @@ -1792,7 +1815,7 @@ void R_RenderPlayerView (player_t* player) { for (y2 = 0; y2 < (first_y ? first_y : MIN(ph, (viewwindowy + viewheight) - y)); y2++) { - memset( + V_RGBSet( dest + ((y + y2) * video.pitch) + x, dest[ ( (first_y ? viewwindowy + first_y diff --git a/src/r_main.h b/src/r_main.h index 737280adc..0a9cff093 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -142,6 +142,8 @@ fixed_t R_GetNughudViewPitch(void); #define POWER_RUNOUT(power) \ ((STRICTMODE(comp_powerrunout) ? (power) >= 4*32 : (power) > 4*32) || (power) & 8) +byte R_GetLightIndexFrac(void); + // FOV effects --------------------------------------------------------------- enum { diff --git a/src/r_plane.c b/src/r_plane.c index 8008192cf..d5dca36ee 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -210,16 +210,53 @@ static void R_MapPlane(int y, int x1, int x2) ds_xfrac = viewx + FixedMul(viewcos, distance) + (dx * ds_xstep) + xoffs; ds_yfrac = -viewy - FixedMul(viewsin, distance) + (dx * ds_ystep) + yoffs; + ds_nextcolormap = NULL; // [Nugget] True color + if (!(ds_colormap[0] = ds_colormap[1] = fixedcolormap)) { - index = distance >> LIGHTZSHIFT; - if (index >= MAXLIGHTZ ) - index = MAXLIGHTZ-1; + // [Nugget] True color + + #define INDEX_PRECISION 255 + + if (truecolor_rendering == TRUECOLOR_FULL) + { + ds_lightindex = ds_minlightindex; + + if (!STRICTMODE(!diminished_lighting)) + { + const fixed_t max = MAXLIGHTZ * (1 << LIGHTZSHIFT), + step = max / 32; + + const fixed_t invdistance = max - distance; + + if (invdistance > step) + { ds_lightindex += invdistance / step; } + } + + ds_lightindex = BETWEEN(0, INDEX_PRECISION, ds_lightindex); + } + else + { + index = distance >> LIGHTZSHIFT; + if (index >= MAXLIGHTZ ) + index = MAXLIGHTZ-1; + + if (STRICTMODE(!diminished_lighting)) { index = MAXLIGHTZ-1; } // [Nugget] + + ds_colormap[0] = planezlight[index]; + ds_colormap[1] = fullcolormap; + + if (truecolor_rendering == TRUECOLOR_HYBRID + && 0 < index + && ds_colormap[0] != planezlight[index - 1]) + { + ds_lightindex = INDEX_PRECISION-1 - ((distance % (1 << LIGHTZSHIFT)) * INDEX_PRECISION / (1 << LIGHTZSHIFT)); - if (STRICTMODE(!diminished_lighting)) { index = MAXLIGHTZ-1; } // [Nugget] + ds_nextcolormap = planezlight[index - 1]; + } + } - ds_colormap[0] = planezlight[index]; - ds_colormap[1] = fullcolormap; + #undef INDEX_PRECISION } ds_y = y; @@ -603,6 +640,8 @@ static void do_draw_plane(visplane_t *pl) return; } + ds_nextcolormap = NULL; // [Nugget] True color + // sky flat if (pl->picnum == skyflatnum && sky) @@ -639,20 +678,29 @@ static void do_draw_plane(visplane_t *pl) xoffs = pl->xoffs; // killough 2/28/98: Add offsets yoffs = pl->yoffs; planeheight = abs(pl->height - viewz); - light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (light >= LIGHTLEVELS) + if (truecolor_rendering == TRUECOLOR_FULL) { - light = LIGHTLEVELS - 1; + ds_minlightindex = pl->lightlevel + (extralight * 16); } - - if (light < 0) + else { - light = 0; + light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (light >= LIGHTLEVELS) + { + light = LIGHTLEVELS - 1; + } + + if (light < 0) + { + light = 0; + } + + planezlight = zlight[light]; } stop = pl->maxx + 1; - planezlight = zlight[light]; pl->top[pl->minx - 1] = pl->top[stop] = USHRT_MAX; for (int x = pl->minx; x <= stop; x++) diff --git a/src/r_segs.c b/src/r_segs.c index c74aedd63..4d0fcdb3c 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -41,6 +41,9 @@ #include "w_wad.h" #include "z_zone.h" +// [Nugget] +#include "i_video.h" + // OPTIMIZE: closed two sided lines as single sided // killough 1/6/98: replaced globals with statics where appropriate @@ -119,27 +122,60 @@ void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2) texnum = texturetranslation[curline->sidedef->midtexture]; - // killough 4/13/98: get correct lightlevel for 2s normal textures - lightnum = (R_FakeFlat(frontsector, &tempsec, NULL, NULL, false) - ->lightlevel >> LIGHTSEGSHIFT)+extralight; + const int lightlevel = R_FakeFlat(frontsector, &tempsec, NULL, NULL, false)->lightlevel; - // [crispy] smoother fake contrast - if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + // [Nugget] True color + if (truecolor_rendering == TRUECOLOR_FULL) { - lightnum += curline->fakecontrast; + #define INDEX_PRECISION 255 + + dc_minlightindex = lightlevel + (extralight * 16); + + int fakecontrast = 0; + + // [crispy] smoother fake contrast + if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + { + fakecontrast = curline->fakecontrast; + } + // [Nugget] Vanilla effect + else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + { + if (curline->v1->y == curline->v2->y) + fakecontrast = -1; + else if (curline->v1->x == curline->v2->x) + fakecontrast = 1; + } + + dc_minlightindex += fakecontrast * 16; + + dc_minlightindex = BETWEEN(0, INDEX_PRECISION, dc_minlightindex); + + #undef INDEX_PRECISION } - // [Nugget] Vanilla effect - else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + else { - if (curline->v1->y == curline->v2->y) - lightnum--; - else - if (curline->v1->x == curline->v2->x) - lightnum++; - } + // killough 4/13/98: get correct lightlevel for 2s normal textures + lightnum = (lightlevel >> LIGHTSEGSHIFT)+extralight; + + // [crispy] smoother fake contrast + if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + { + lightnum += curline->fakecontrast; + } + // [Nugget] Vanilla effect + else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + { + if (curline->v1->y == curline->v2->y) + lightnum--; + else + if (curline->v1->x == curline->v2->x) + lightnum++; + } - walllights = lightnum >= LIGHTLEVELS ? scalelight[LIGHTLEVELS-1] : - lightnum < 0 ? scalelight[0] : scalelight[lightnum]; + walllights = lightnum >= LIGHTLEVELS ? scalelight[LIGHTLEVELS-1] : + lightnum < 0 ? scalelight[0] : scalelight[lightnum]; + } maskedtexturecol = ds->maskedtexturecol; @@ -171,15 +207,47 @@ void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2) for (dc_x = x1 ; dc_x <= x2 ; dc_x++, spryscale += rw_scalestep) if (maskedtexturecol[dc_x] != INT_MAX) // [FG] 32-bit integer math { - if (!fixedcolormap) // calculate lighting - { // killough 11/98: - const int index = STRICTMODE(!diminished_lighting) // [Nugget] - ? 0 : R_GetLightIndex(spryscale); + dc_nextcolormap = NULL; // [Nugget] True color + if (!fixedcolormap) // calculate lighting + { // [crispy] brightmaps for two sided mid-textures dc_brightmap = texturebrightmap[texnum]; - dc_colormap[0] = walllights[index]; - dc_colormap[1] = STRICTMODE(brightmaps) ? fullcolormap : dc_colormap[0]; + + // [Nugget] True color + + if (truecolor_rendering == TRUECOLOR_FULL) + { + #define INDEX_PRECISION 255 + + dc_lightindex = dc_minlightindex; + + if (!STRICTMODE(!diminished_lighting)) + { + R_GetLightIndex(spryscale); + dc_lightindex += R_GetLightIndexFrac(); + } + + dc_lightindex = BETWEEN(0, INDEX_PRECISION, dc_lightindex); + + #undef INDEX_PRECISION + } + else + { + const int index = STRICTMODE(!diminished_lighting) // [Nugget] + ? 0 : R_GetLightIndex(spryscale); + + dc_colormap[0] = walllights[index]; + dc_colormap[1] = STRICTMODE(brightmaps) ? fullcolormap : dc_colormap[0]; + + if (truecolor_rendering == TRUECOLOR_HYBRID + && index < MAXLIGHTSCALE-1 + && dc_colormap[0] != walllights[index + 1]) + { + dc_lightindex = R_GetLightIndexFrac(); + dc_nextcolormap = walllights[index + 1]; + } + } } // killough 3/2/98: @@ -383,21 +451,53 @@ static void R_RenderSegLoop (void) // texturecolumn and lighting are independent of wall tiers if (segtextured) { - const int index = STRICTMODE(!diminished_lighting) // [Nugget] - ? 0 : R_GetLightIndex(rw_scale); - // calculate texture offset angle_t angle =(rw_centerangle+xtoviewangle[rw_x])>>ANGLETOFINESHIFT; angle &= 0xFFF; // Prevent finetangent overflow. texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); texturecolumn >>= FRACBITS; - // calculate lighting - dc_colormap[0] = walllights[index]; - dc_colormap[1] = (!fixedcolormap && STRICTMODE(brightmaps)) ? - fullcolormap : dc_colormap[0]; dc_x = rw_x; dc_iscale = 0xffffffffu / (unsigned)rw_scale; + + // calculate lighting + // [Nugget] True color + + dc_nextcolormap = NULL; + + if (truecolor_rendering == TRUECOLOR_FULL && !fixedcolormap) + { + #define INDEX_PRECISION 255 + + dc_lightindex = dc_minlightindex; + + if (!STRICTMODE(!diminished_lighting)) + { + R_GetLightIndex(spryscale); + dc_lightindex += R_GetLightIndexFrac(); + } + + dc_lightindex = BETWEEN(0, INDEX_PRECISION, dc_lightindex); + + #undef INDEX_PRECISION + } + else + { + const int index = STRICTMODE(!diminished_lighting) // [Nugget] + ? 0 : R_GetLightIndex(rw_scale); + + dc_colormap[0] = walllights[index]; + dc_colormap[1] = (!fixedcolormap && STRICTMODE(brightmaps)) ? + fullcolormap : dc_colormap[0]; + + if (truecolor_rendering == TRUECOLOR_HYBRID + && index < MAXLIGHTSCALE-1 + && dc_colormap[0] != walllights[index + 1]) + { + dc_lightindex = R_GetLightIndexFrac(); + dc_nextcolormap = walllights[index + 1]; + } + } } // draw the wall tiers @@ -797,28 +897,60 @@ void R_StoreWallRange(const int start, const int stop) // OPTIMIZE: get rid of LIGHTSEGSHIFT globally if (!fixedcolormap) { - int lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - - // [crispy] smoother fake contrast - if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + // [Nugget] True color + if (truecolor_rendering == TRUECOLOR_FULL) { - lightnum += curline->fakecontrast; + #define INDEX_PRECISION 255 + + dc_minlightindex = frontsector->lightlevel + (extralight * 16); + + int fakecontrast = 0; + + // [crispy] smoother fake contrast + if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + { + fakecontrast = curline->fakecontrast; + } + // [Nugget] Vanilla effect + else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + { + if (curline->v1->y == curline->v2->y) + fakecontrast = -1; + else if (curline->v1->x == curline->v2->x) + fakecontrast = 1; + } + + dc_minlightindex += fakecontrast * 16; + + dc_minlightindex = BETWEEN(0, INDEX_PRECISION, dc_minlightindex); + + #undef INDEX_PRECISION } - // [Nugget] Vanilla effect - else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + else { - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - } + int lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; - else - walllights = scalelight[lightnum]; + // [crispy] smoother fake contrast + if (BETWEEN(strictmode, 2, fake_contrast) == 1) // [Nugget] + { + lightnum += curline->fakecontrast; + } + // [Nugget] Vanilla effect + else if (BETWEEN(strictmode, 2, fake_contrast) == 2) + { + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + } + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; + } } } diff --git a/src/r_things.c b/src/r_things.c index 2c6bc8352..d37dc817c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -442,6 +442,10 @@ void R_DrawVisSprite(vissprite_t *vis, int x1, int x2) dc_colormap[1] = vis->colormap[1]; dc_brightmap = vis->brightmap; + // [Nugget] True color + dc_lightindex = vis->lightindex; + dc_nextcolormap = vis->nextcolormap; + // killough 4/11/98: rearrange and handle translucent sprites // mixed with translucent/non-translucent 2s normals @@ -714,20 +718,58 @@ static void R_ProjectSprite (mobj_t* thing) vis->startfrac += vis->xiscale*(vis->x1-x1); vis->patch = lump; + vis->nextcolormap = NULL; // [Nugget] True color + // get light level if (thing->flags & MF_SHADOW) vis->colormap[0] = vis->colormap[1] = NULL; // shadow draw else if (fixedcolormap) vis->colormap[0] = vis->colormap[1] = fixedcolormap; // fixed map else if (frame & FF_FULLBRIGHT) + { vis->colormap[0] = vis->colormap[1] = fullcolormap; // full bright // killough 3/20/98 + vis->lightindex = 255; // [Nugget] True color + } else - { // diminished light - const int index = STRICTMODE(!diminished_lighting) // [Nugget] - ? 0 : R_GetLightIndex(xscale); + { + // diminished light + // [Nugget] True color + + if (truecolor_rendering == TRUECOLOR_FULL) + { + #define INDEX_PRECISION 255 + + vis->lightindex = dc_minlightindex; + + if (!STRICTMODE(!diminished_lighting)) + { + R_GetLightIndex(xscale); + vis->lightindex += R_GetLightIndexFrac(); + } - vis->colormap[0] = spritelights[index]; - vis->colormap[1] = fullcolormap; + vis->lightindex = BETWEEN(0, INDEX_PRECISION, vis->lightindex); + + #undef INDEX_PRECISION + + // Assign a colormap so that it doesn't apply the fuzz effect + vis->colormap[0] = scalelight[0][0]; + } + else + { + const int index = STRICTMODE(!diminished_lighting) // [Nugget] + ? 0 : R_GetLightIndex(xscale); + + vis->colormap[0] = spritelights[index]; + vis->colormap[1] = fullcolormap; + + if (truecolor_rendering == TRUECOLOR_HYBRID + && index < MAXLIGHTSCALE-1 + && vis->colormap[0] != spritelights[index + 1]) + { + vis->lightindex = R_GetLightIndexFrac(); + vis->nextcolormap = spritelights[index + 1]; + } + } } vis->brightmap = R_BrightmapForState(thing->state - states); @@ -781,14 +823,22 @@ void R_AddSprites(sector_t* sec, int lightlevel) if (demo_version <= DV_BOOM) lightlevel = sec->lightlevel; - lightnum = (lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; + // [Nugget] True color + if (truecolor_rendering == TRUECOLOR_FULL) + { + dc_minlightindex = lightlevel + (extralight * 16); + } else - spritelights = scalelight[lightnum]; + { + lightnum = (lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + } // Handle all things in sector. @@ -958,6 +1008,8 @@ void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent vis->patch = lump; + vis->nextcolormap = NULL; // [Nugget] True color + // killough 7/11/98: beta psprites did not draw shadows if (POWER_RUNOUT(viewplayer->powers[pw_invisibility]) && !beta_emulation) @@ -973,6 +1025,15 @@ void R_DrawPSprite (pspdef_t *psp, boolean translucent) // [Nugget] Translucent vis->colormap[0] = spritelights[index]; // local light vis->colormap[1] = fullcolormap; + + // [Nugget] True color ------------------------------------------------- + + if (truecolor_rendering == TRUECOLOR_FULL) + { + vis->lightindex = dc_minlightindex + index; + + vis->lightindex = BETWEEN(0, 255, vis->lightindex); + } } vis->brightmap = R_BrightmapForState(psp->state - states); @@ -1010,15 +1071,25 @@ void R_DrawPlayerSprites(void) R_FakeFlat(viewplayer->mo->subsector->sector, &tmpsec, &floorlightlevel, &ceilinglightlevel, 0); - lightnum = ((floorlightlevel+ceilinglightlevel) >> (LIGHTSEGSHIFT+1)) - + extralight; - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; - else - spritelights = scalelight[lightnum]; + // [Nugget] True color + if (truecolor_rendering == TRUECOLOR_FULL) + { + dc_minlightindex = ((floorlightlevel + ceilinglightlevel) >> 1) + + (extralight * 16); + } + //else + { + lightnum = ((floorlightlevel+ceilinglightlevel) >> (LIGHTSEGSHIFT+1)) + + extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + } // clip to screen bounds mfloorclip = screenheightarray; diff --git a/src/r_voxel.c b/src/r_voxel.c index 7d2903e35..c1a6f77e3 100644 --- a/src/r_voxel.c +++ b/src/r_voxel.c @@ -835,7 +835,7 @@ static void VX_DrawColumn (vissprite_t * spr, int x, int y) boolean shadow = ((spr->mobjflags & MF_SHADOW) != 0); int linesize = video.pitch; - byte * dest = I_VideoBuffer + viewwindowy * linesize + viewwindowx; + pixel_t * dest = I_VideoBuffer + viewwindowy * linesize + viewwindowx; // iterate over screen columns fixed_t ux = ((Ax - 1) | FRACMASK) + 1; @@ -931,7 +931,7 @@ static void VX_DrawColumn (vissprite_t * spr, int x, int y) for (; uy < uy1 ; uy += FRACUNIT) { - dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = pix; + dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = V_IndexToRGB(pix); } } else if (has_bottom) @@ -946,7 +946,7 @@ static void VX_DrawColumn (vissprite_t * spr, int x, int y) for (; uy > uy2 ; uy -= FRACUNIT) { - dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = pix; + dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = V_IndexToRGB(pix); } } @@ -964,7 +964,7 @@ static void VX_DrawColumn (vissprite_t * spr, int x, int y) byte src = slab[i]; byte pix = spr->colormap[spr->brightmap[src]][src]; - dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = pix; + dest[(uy >> FRACBITS) * linesize + (ux >> FRACBITS)] = V_IndexToRGB(pix); } } } diff --git a/src/st_stuff.c b/src/st_stuff.c index cfdc1d3cc..b13a90fb7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1803,22 +1803,40 @@ static void DrawSolidBackground(void) int x, y; const int v0 = vstep[v][0], v1 = vstep[v][1]; unsigned r = 0, g = 0, b = 0; - byte col; + pixel_t col; for (y = v0; y < v1; y++) { for (x = 0; x < depth; x++) { - byte *c = st_backing_screen + V_ScaleY(y) * video.pitch + pixel_t *c = st_backing_screen + V_ScaleY(y) * video.pitch + V_ScaleX(x); - r += pal[3 * c[0] + 0]; - g += pal[3 * c[0] + 1]; - b += pal[3 * c[0] + 2]; + + if (truecolor_rendering) + { + r += V_RedFromRGB(*c); + g += V_GreenFromRGB(*c); + b += V_BlueFromRGB(*c); + } + else { + r += pal[3 * V_IndexFromRGB(c[0]) + 0]; + g += pal[3 * V_IndexFromRGB(c[0]) + 1]; + b += pal[3 * V_IndexFromRGB(c[0]) + 2]; + } c += V_ScaleX(width - 2 * x - 1); - r += pal[3 * c[0] + 0]; - g += pal[3 * c[0] + 1]; - b += pal[3 * c[0] + 2]; + + if (truecolor_rendering) + { + r += V_RedFromRGB(*c); + g += V_GreenFromRGB(*c); + b += V_BlueFromRGB(*c); + } + else { + r += pal[3 * V_IndexFromRGB(c[0]) + 0]; + g += pal[3 * V_IndexFromRGB(c[0]) + 1]; + b += pal[3 * V_IndexFromRGB(c[0]) + 2]; + } } } @@ -1827,9 +1845,18 @@ static void DrawSolidBackground(void) b /= 2 * depth * (v1 - v0); // [FG] tune down to half saturation (for empiric reasons) - col = I_GetNearestColor(pal, r / 2, g / 2, b / 2); + if (truecolor_rendering) + { + col = ((r / 2) << PIXEL_RED_SHIFT) + | ((g / 2) << PIXEL_GREEN_SHIFT) + | ((b / 2) << PIXEL_BLUE_SHIFT); + } + else + { + col = V_IndexToRGB(I_GetNearestColor(pal, r / 2, g / 2, b / 2)); + } - V_FillRect(0, v0, video.unscaledw, v1 - v0, col); + V_FillRectRGB(0, v0, video.unscaledw, v1 - v0, col); } } @@ -2135,6 +2162,8 @@ static void DoPaletteStuff(player_t *player) // a GNU C extension I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE) + palette * 768); + + V_SetPalColors(palette); } } diff --git a/src/st_widgets.c b/src/st_widgets.c index b3a4b8960..f2f1b9dbb 100644 --- a/src/st_widgets.c +++ b/src/st_widgets.c @@ -487,7 +487,7 @@ typedef struct int pos; } chatline_t; -static chatline_t lines[MAXPLAYERS]; +static chatline_t chatlines[MAXPLAYERS]; static void ClearChatLine(chatline_t *line) { @@ -560,20 +560,20 @@ void ST_UpdateChatMessage(void) ch = (char)shiftxform[(unsigned char)ch]; } - if (AddKeyToChatLine(&lines[p], ch) && ch == KEY_ENTER) + if (AddKeyToChatLine(&chatlines[p], ch) && ch == KEY_ENTER) { - if (lines[p].pos && (chat_dest[p] == consoleplayer + 1 + if (chatlines[p].pos && (chat_dest[p] == consoleplayer + 1 || chat_dest[p] == HU_BROADCAST)) { M_snprintf(message_string, sizeof(message_string), - "%s%s", *player_names[p], lines[p].string); + "%s%s", *player_names[p], chatlines[p].string); S_StartSoundPitch(0, gamemode == commercial ? sfx_radio : sfx_tink, PITCH_NONE); } - ClearChatLine(&lines[p]); + ClearChatLine(&chatlines[p]); } } players[p].cmd.chatchar = 0; diff --git a/src/v_video.c b/src/v_video.c index bee247164..0a5a69ce9 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -46,6 +46,9 @@ #include "w_wad.h" // needed for color translation lump lookup #include "z_zone.h" +// [Nugget] +#include "i_gamma.h" + pixel_t *I_VideoBuffer; // The screen buffer that the v_video.c code draws to. @@ -164,6 +167,96 @@ byte cr_allblack[256], cr_gray_vc[256], // `V_Colorize()` only nightvision[256]; // Night-vision visor +// True color ---------------------------------------------------------------- + +int *palcolors, palscolors[14][256]; + +// [JN] Saturation percent array. +// 0.66 = 0% saturation, 0.0 = 100% saturation. +const float I_SaturationPercent[101] = +{ + 0.660000f, 0.653400f, 0.646800f, 0.640200f, 0.633600f, + 0.627000f, 0.620400f, 0.613800f, 0.607200f, 0.600600f, + 0.594000f, 0.587400f, 0.580800f, 0.574200f, 0.567600f, + 0.561000f, 0.554400f, 0.547800f, 0.541200f, 0.534600f, + 0.528000f, 0.521400f, 0.514800f, 0.508200f, 0.501600f, + 0.495000f, 0.488400f, 0.481800f, 0.475200f, 0.468600f, + 0.462000f, 0.455400f, 0.448800f, 0.442200f, 0.435600f, + 0.429000f, 0.422400f, 0.415800f, 0.409200f, 0.402600f, + 0.396000f, 0.389400f, 0.382800f, 0.376200f, 0.369600f, + 0.363000f, 0.356400f, 0.349800f, 0.343200f, 0.336600f, + 0.330000f, 0.323400f, 0.316800f, 0.310200f, 0.303600f, + 0.297000f, 0.290400f, 0.283800f, 0.277200f, 0.270600f, + 0.264000f, 0.257400f, 0.250800f, 0.244200f, 0.237600f, + 0.231000f, 0.224400f, 0.217800f, 0.211200f, 0.204600f, + 0.198000f, 0.191400f, 0.184800f, 0.178200f, 0.171600f, + 0.165000f, 0.158400f, 0.151800f, 0.145200f, 0.138600f, + 0.132000f, 0.125400f, 0.118800f, 0.112200f, 0.105600f, + 0.099000f, 0.092400f, 0.085800f, 0.079200f, 0.072600f, + 0.066000f, 0.059400f, 0.052800f, 0.046200f, 0.039600f, + 0.033000f, 0.026400f, 0.019800f, 0.013200f, 0, + 0 +}; + +void V_InitPalsColors(void) +{ + const byte *const playpal = W_CacheLumpName("PLAYPAL", PU_CACHE); + const byte *const gamma = gammatable[gamma2]; + + for (int i = 0; i < 14; i++) + { + int *const pc = palscolors[i]; + const byte *const pal = playpal + (768 * i); + + for (int j = 0; j < 256; j++) + { + // [Nugget] Color settings + + const byte r = gamma[pal[(j * 3) + 0]] * red_intensity / 100, + g = gamma[pal[(j * 3) + 1]] * green_intensity / 100, + b = gamma[pal[(j * 3) + 2]] * blue_intensity / 100; + + // [PN] Contrast adjustment + + const int contrast_adjustment = 128 * (100 - color_contrast) / 100; + + int channels[3] = { + ((int) r * color_contrast / 100) + contrast_adjustment, + ((int) g * color_contrast / 100) + contrast_adjustment, + ((int) b * color_contrast / 100) + contrast_adjustment + }; + + channels[0] = BETWEEN(0, 255, channels[0]); + channels[1] = BETWEEN(0, 255, channels[1]); + channels[2] = BETWEEN(0, 255, channels[2]); + + // [JN] Saturation floats, high and low. + // If saturation has been modified (< 100), set high and low + // values according to saturation level. Sum of r,g,b channels + // and floats must be 1.0 to get proper colors. + + float a_hi = I_SaturationPercent[color_saturation], + a_lo = a_hi / 2.0f; + + a_hi = 1.0f - a_hi; + a_lo = 0.0f + a_lo; + + // Calculate final color values + pc[j] = ((byte) ((a_hi * channels[0]) + (a_lo * channels[1]) + (a_lo * channels[2])) + << PIXEL_RED_SHIFT) + | ((byte) ((a_lo * channels[0]) + (a_hi * channels[1]) + (a_lo * channels[2])) + << PIXEL_GREEN_SHIFT) + | ((byte) ((a_lo * channels[0]) + (a_lo * channels[1]) + (a_hi * channels[2])) + << PIXEL_BLUE_SHIFT); + } + } +} + +void V_SetPalColors(const int palette_index) +{ + palcolors = palscolors[palette_index]; +} + // [Nugget] -----------------------------------------------------------------/ // killough 5/2/98: tiny engine driven by table above @@ -332,7 +425,7 @@ static void (*drawcolfunc)(const patch_column_t *patchcol); patchcol->y2, patchcol->x); \ } \ \ - byte *dest = V_ADDRESS(dest_screen, patchcol->x, patchcol->y1); \ + pixel_t *dest = V_ADDRESS(dest_screen, patchcol->x, patchcol->y1); \ \ const fixed_t fracstep = patchcol->step; \ fixed_t frac = \ @@ -342,33 +435,33 @@ static void (*drawcolfunc)(const patch_column_t *patchcol); \ while ((count -= 2) >= 0) \ { \ - *dest = SRCPIXEL; \ + *dest = V_IndexToRGB(SRCPIXEL); \ dest += linesize; \ frac += fracstep; \ - *dest = SRCPIXEL; \ + *dest = V_IndexToRGB(SRCPIXEL); \ dest += linesize; \ frac += fracstep; \ } \ if (count & 1) \ { \ - *dest = SRCPIXEL; \ + *dest = V_IndexToRGB(SRCPIXEL); \ } \ } DRAW_COLUMN(, source[frac >> FRACBITS]) DRAW_COLUMN(TR, translation[source[frac >> FRACBITS]]) DRAW_COLUMN(TRTR, translation2[translation1[source[frac >> FRACBITS]]]) -DRAW_COLUMN(TL, tranmap[(*dest << 8) + source[frac >> FRACBITS]]) -DRAW_COLUMN(TRTL, tranmap[(*dest << 8) + translation[source[frac >> FRACBITS]]]) +DRAW_COLUMN(TL, tranmap[(V_IndexFromRGB(*dest) << 8) + source[frac >> FRACBITS]]) +DRAW_COLUMN(TRTL, tranmap[(V_IndexFromRGB(*dest) << 8) + translation[source[frac >> FRACBITS]]]) // [Nugget] /----------------------------------------------------------------- -DRAW_COLUMN(TRTRTL, tranmap[(*dest << 8) + translation2[translation1[source[frac >> FRACBITS]]]]) +DRAW_COLUMN(TRTRTL, tranmap[(V_IndexFromRGB(*dest) << 8) + translation2[translation1[source[frac >> FRACBITS]]]]) DRAW_COLUMN( Translucent2, tranmap[ - (*dest << 8) + (V_IndexFromRGB(*dest) << 8) + (translation2 ? translation2[translation1[source[frac >> FRACBITS]]] : translation1 ? translation1[source[frac >> FRACBITS]] : source[frac >> FRACBITS] ) @@ -745,17 +838,25 @@ void V_ShadeScreen(const int level) // [Nugget] { const byte *darkcolormap = &colormaps[0][level * 256]; - byte *row = dest_screen; + pixel_t *row = dest_screen; int height = video.height; while (height--) { int width = video.width; - byte *col = row; + pixel_t *col = row; while (width--) { - *col = darkcolormap[*col]; + if (truecolor_rendering) + { + *col = V_ShadeRGB(*col, level, 32); + } + else + { + *col = V_IndexToRGB(darkcolormap[V_IndexFromRGB(*col)]); + } + ++col; } @@ -814,7 +915,7 @@ static void ScaleClippedRect(vrect_t *rect) rect->sh = y2lookup[rect->cy2] - rect->sy + 1; } -void V_FillRect(int x, int y, int width, int height, byte color) +void V_FillRectRGB(int x, int y, int width, int height, pixel_t color) { vrect_t dstrect; @@ -833,11 +934,11 @@ void V_FillRect(int x, int y, int width, int height, byte color) ScaleClippedRect(&dstrect); - byte *dest = V_ADDRESS(dest_screen, dstrect.sx, dstrect.sy); + pixel_t *dest = V_ADDRESS(dest_screen, dstrect.sx, dstrect.sy); while (dstrect.sh--) { - memset(dest, color, dstrect.sw); + V_RGBSet(dest, color, dstrect.sw); dest += linesize; } } @@ -862,15 +963,18 @@ void V_ShadowRect(int x, int y, int width, int height) ScaleClippedRect(&dstrect); - byte *dest = V_ADDRESS(dest_screen, dstrect.sx, dstrect.sy); + pixel_t *dest = V_ADDRESS(dest_screen, dstrect.sx, dstrect.sy); while (dstrect.sh--) { for (int x = 0; x < dstrect.sw; x++) { - byte *const d = &dest[x]; + pixel_t *const d = &dest[x]; - *d = R_GetGenericTranMap(hud_menu_shadows_filter_pct)[*d << 8]; + *d = V_IndexToRGB( + R_GetGenericTranMap(hud_menu_shadows_filter_pct) + [V_IndexFromRGB(*d) << 8] + ); } dest += linesize; @@ -889,7 +993,7 @@ void V_CopyRect(int srcx, int srcy, pixel_t *source, int width, int height, int destx, int desty) { vrect_t srcrect, dstrect; - byte *src, *dest; + pixel_t *src, *dest; int usew, useh; #ifdef RANGECHECK @@ -940,7 +1044,7 @@ void V_CopyRect(int srcx, int srcy, pixel_t *source, int width, int height, while (useh--) { - memcpy(dest, src, usew); + V_RGBCopy(dest, src, usew); src += linesize; dest += linesize; } @@ -957,8 +1061,8 @@ void V_CopyRect(int srcx, int srcy, pixel_t *source, int width, int height, void V_DrawBlock(int x, int y, int width, int height, pixel_t *src) { - const byte *source; - byte *dest; + const pixel_t *source; + pixel_t *dest; vrect_t dstrect; dstrect.x = x; @@ -987,7 +1091,7 @@ void V_DrawBlock(int x, int y, int width, int height, pixel_t *src) int w; fixed_t xfrac, yfrac; int xtex, ytex; - byte *row; + pixel_t *row; yfrac = 0; @@ -1013,7 +1117,7 @@ void V_DrawBlock(int x, int y, int width, int height, pixel_t *src) void V_TileBlock64(int line, int width, int height, const byte *src) { - byte *dest, *row; + pixel_t *dest, *row; fixed_t xfrac, yfrac; int xtex, ytex, h; vrect_t dstrect; @@ -1040,7 +1144,7 @@ void V_TileBlock64(int line, int width, int height, const byte *src) while (w--) { xtex = (xfrac >> FRACBITS) & 63; - *row++ = src[ytex + xtex]; + *row++ = V_IndexToRGB(src[ytex + xtex]); xfrac += video.xstep; } @@ -1059,9 +1163,9 @@ void V_TileBlock64(int line, int width, int height, const byte *src) // No return value // -void V_GetBlock(int x, int y, int width, int height, byte *dest) +void V_GetBlock(int x, int y, int width, int height, pixel_t *dest) { - byte *src; + pixel_t *src; #ifdef RANGECHECK if (x < 0 || x + width > video.width || y < 0 || y + height > video.height) @@ -1074,7 +1178,7 @@ void V_GetBlock(int x, int y, int width, int height, byte *dest) while (height--) { - memcpy(dest, src, width); + V_RGBCopy(dest, src, width); src += linesize; dest += width; } @@ -1082,9 +1186,9 @@ void V_GetBlock(int x, int y, int width, int height, byte *dest) // [FG] non hires-scaling variant of V_DrawBlock, used in disk icon drawing -void V_PutBlock(int x, int y, int width, int height, byte *src) +void V_PutBlock(int x, int y, int width, int height, pixel_t *src) { - byte *dest; + pixel_t *dest; #ifdef RANGECHECK if (x < 0 || x + width > video.width || y < 0 || y + height > video.height) @@ -1097,7 +1201,7 @@ void V_PutBlock(int x, int y, int width, int height, byte *src) while (height--) { - memcpy(dest, src, width); + V_RGBCopy(dest, src, width); dest += linesize; src += width; } @@ -1163,6 +1267,10 @@ void V_Init(void) } y2lookup[SCREENHEIGHT - 1] = video.height - 1; y1lookup[SCREENHEIGHT] = y2lookup[SCREENHEIGHT] = video.height; + + // [Nugget] True color + V_InitPalsColors(); + V_SetPalColors(0); } // Set the buffer that the code draws to. diff --git a/src/v_video.h b/src/v_video.h index 6c11fc6b0..0adc51485 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -26,6 +26,9 @@ #include "doomtype.h" #include "m_fixed.h" +// [Nugget] +#include "r_state.h" + struct patch_s; // @@ -182,6 +185,81 @@ void V_DrawPatchTRTL(int x, int y, struct patch_s *patch, byte *outr, byte *tl); extern int automap_overlay_darkening; extern int menu_backdrop_darkening; +// True color ---------------------------------------------------------------- + +extern int *palcolors, palscolors[14][256]; + +void V_InitPalsColors(void); +void V_SetPalColors(const int palette_index); + +// The upper byte corresponding to the alpha channel +// actually stores the index from which the color derives + +#define PIXEL_INDEX_SHIFT 24 +#define PIXEL_RED_SHIFT 16 +#define PIXEL_GREEN_SHIFT 8 +#define PIXEL_BLUE_SHIFT 0 + +#define PIXEL_INDEX_MASK (0xFF << PIXEL_INDEX_SHIFT) +#define PIXEL_RED_MASK (0xFF << PIXEL_RED_SHIFT) +#define PIXEL_GREEN_MASK (0xFF << PIXEL_GREEN_SHIFT) +#define PIXEL_BLUE_MASK (0xFF << PIXEL_BLUE_SHIFT) + +inline static pixel_t V_IndexToRGB(const byte index) +{ + return (index << PIXEL_INDEX_SHIFT) | palcolors[index]; +} + +inline static byte V_IndexFromRGB(const pixel_t rgb) +{ + return (rgb & PIXEL_INDEX_MASK) >> PIXEL_INDEX_SHIFT; +} + +inline static byte V_RedFromRGB(const pixel_t rgb) +{ + return (rgb & PIXEL_RED_MASK) >> PIXEL_RED_SHIFT; +} + +inline static byte V_GreenFromRGB(const pixel_t rgb) +{ + return (rgb & PIXEL_GREEN_MASK) >> PIXEL_GREEN_SHIFT; +} + +inline static byte V_BlueFromRGB(const pixel_t rgb) +{ + return (rgb & PIXEL_BLUE_MASK) >> PIXEL_BLUE_SHIFT; +} + +#define V_IndexSet(dest, color, count) V_RGBSet(dest, V_IndexToRGB(color), count) +inline static void V_RGBSet(pixel_t *const dest, const pixel_t color, const int count) +{ + for (int i = 0; i < count; i++) { dest[i] = color; } +} + +inline static void V_RGBCopy(pixel_t *const dest, const pixel_t *const src, const int count) +{ + for (int i = 0; i < count; i++) { dest[i] = src[i]; } +} + +inline static pixel_t V_LerpRGB(const pixel_t a, const pixel_t b, const byte level, const byte maxlevel) +{ + return (a & PIXEL_INDEX_MASK) + | (((V_RedFromRGB(a) * (maxlevel - level) / maxlevel) + + (V_RedFromRGB(b) * level / maxlevel)) << PIXEL_RED_SHIFT) + | (((V_GreenFromRGB(a) * (maxlevel - level) / maxlevel) + + (V_GreenFromRGB(b) * level / maxlevel)) << PIXEL_GREEN_SHIFT) + | (((V_BlueFromRGB(a) * (maxlevel - level) / maxlevel) + + (V_BlueFromRGB(b) * level / maxlevel)) << PIXEL_BLUE_SHIFT); +} + +inline static pixel_t V_ShadeRGB(const pixel_t rgb, const int level, const int maxlevel) +{ + return (rgb & PIXEL_INDEX_MASK) + | ((V_RedFromRGB(rgb) * (maxlevel - level) / maxlevel) << PIXEL_RED_SHIFT) + | ((V_GreenFromRGB(rgb) * (maxlevel - level) / maxlevel) << PIXEL_GREEN_SHIFT) + | ((V_BlueFromRGB(rgb) * (maxlevel - level) / maxlevel) << PIXEL_BLUE_SHIFT); +} + // HUD/menu shadows ---------------------------------------------------------- extern boolean hud_menu_shadows; @@ -263,7 +341,10 @@ void V_GetBlock(int x, int y, int width, int height, pixel_t *dest); void V_PutBlock(int x, int y, int width, int height, pixel_t *src); -void V_FillRect(int x, int y, int width, int height, byte color); +#define V_FillRect(x, y, w, h, c) \ + V_FillRectRGB(x, y, w, h, V_IndexToRGB(c)) + +void V_FillRectRGB(int x, int y, int width, int height, pixel_t color); void V_TileBlock64(int line, int width, int height, const byte *src);