From 6476a92817fee8fcb3c3bf6f832a881393d5a989 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Wed, 25 Dec 2019 18:46:30 -0500 Subject: [PATCH 1/6] Update blend textures to smooth out colors that have duplicate indices --- src/hardware/hw_md2.c | 101 ++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 3800b6ad9..23145b525 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -654,10 +654,14 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; + UINT8 i; + + UINT8 translation[16]; // First the color index + UINT8 cutoff[16]; // Brightness cutoff before using the next color + UINT8 translen = 0; - // vanilla port - UINT8 translation[16]; memset(translation, 0, sizeof(translation)); + memset(cutoff, 0, sizeof(cutoff)); if (grmip->width == 0) { @@ -684,7 +688,33 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, blendcolor = V_GetColor(0); // initialize if (color != SKINCOLOR_NONE) - memcpy(&translation, &Color_Index[color - 1], 16); + { + UINT8 numdupes = 1; + + translation[translen] = Color_Index[color-1][0]; + cutoff[translen] = 255; + + for (i = 1; i < 16; i++) + { + if (translation[translen] == Color_Index[color-1][i]) + { + numdupes++; + continue; + } + + if (translen > 0) + { + cutoff[translen] = cutoff[translen-1] - (256 / (16 / numdupes)); + } + + numdupes = 1; + translen++; + + translation[translen] = (UINT8)Color_Index[color-1][i]; + } + + translen++; + } while (size--) { @@ -710,7 +740,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, // Turn everything below a certain blue threshold white if (image->s.red == 0 && image->s.green == 0 && image->s.blue <= 82) { - cur->s.red = cur->s.green = cur->s.blue = 255; + cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); } else { @@ -762,6 +792,8 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, { UINT16 brightness; + I_Assert(translen > 0); + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 if (skinnum == TC_RAINBOW) { @@ -798,8 +830,8 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) { RGBA_t nextcolor; - UINT8 firsti, secondi, mul; - UINT32 r, g, b; + UINT8 firsti, secondi, mul, mulmax; + INT32 r, g, b; // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. // Ensue horrible mess. @@ -808,7 +840,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, UINT16 brightdif = 256; UINT8 colorbrightnesses[16]; INT32 compare, m, d; - UINT8 i; // Ignore pure white & pitch black if (brightness > 253 || brightness < 2) @@ -820,18 +851,21 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, firsti = 0; mul = 0; + mulmax = 1; - for (i = 0; i < 16; i++) + for (i = 0; i < translen; i++) { RGBA_t tempc = V_GetColor(translation[i]); SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison } - for (i = 0; i < 16; i++) + for (i = 0; i < translen; i++) { if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) continue; + compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); + if (compare < brightdif) { brightdif = (UINT16)compare; @@ -840,7 +874,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, } secondi = firsti+1; // next color in line - if (secondi == 16) + if (secondi >= translen) { m = (INT16)brightness; // - 0; d = (INT16)colorbrightnesses[firsti]; // - 0; @@ -856,38 +890,57 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, // calculate the "gradient" multiplier based on how close this color is to the one next in line if (m <= 0 || d <= 0) + { mul = 0; + } else - mul = 15 - ((m * 16) / d); + { + mulmax = cutoff[firsti]; + if (secondi < translen) + mulmax -= cutoff[secondi]; + + mul = (mulmax-1) - ((m * mulmax) / d); + } } else { - // Thankfully, it's normally way more simple. - // Just convert brightness to a skincolor value, use remainder to find the gradient multipler - firsti = ((UINT8)(255-brightness) / 16); + // Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler + firsti = 0; + + for (i = 1; i < translen; i++) + { + if (brightness >= cutoff[i]) + break; + firsti = i; + } + secondi = firsti+1; - mul = ((UINT8)(255-brightness) % 16); + + mulmax = cutoff[firsti]; + if (secondi < translen) + mulmax -= cutoff[secondi]; + + mul = cutoff[firsti] - brightness; } blendcolor = V_GetColor(translation[firsti]); - if (mul > 0 // If it's 0, then we only need the first color. - && translation[firsti] != translation[secondi]) // Some colors have duplicate colors in a row, so let's just save the process + if (mul > 0) // If it's 0, then we only need the first color. { - if (secondi == 16) // blend to black + if (secondi >= translen) // blend to black nextcolor = V_GetColor(31); else nextcolor = V_GetColor(translation[secondi]); // Find difference between points - r = (UINT32)(nextcolor.s.red - blendcolor.s.red); - g = (UINT32)(nextcolor.s.green - blendcolor.s.green); - b = (UINT32)(nextcolor.s.blue - blendcolor.s.blue); + r = (INT32)(nextcolor.s.red - blendcolor.s.red); + g = (INT32)(nextcolor.s.green - blendcolor.s.green); + b = (INT32)(nextcolor.s.blue - blendcolor.s.blue); // Find the gradient of the two points - r = ((mul * r) / 16); - g = ((mul * g) / 16); - b = ((mul * b) / 16); + r = ((mul * r) / mulmax); + g = ((mul * g) / mulmax); + b = ((mul * b) / mulmax); // Add gradient value to color blendcolor.s.red += r; From ac365a0c81204f756ad91a0b07e69748e8e70ac9 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Wed, 25 Dec 2019 20:09:31 -0500 Subject: [PATCH 2/6] Fake contrast --- src/hardware/hw_main.c | 66 +++++++++++++++++++++++++++++++++++------- src/hardware/hw_main.h | 1 + 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2f986085a..9f6e497a6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1026,6 +1026,46 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) } #endif +static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) +{ + INT16 finallight = lightnum; + + if (cv_grfakecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_grfakecontrast.value == 2) // Smooth setting + { + extralight = -(contrast<>1)) >> FRACBITS; + } + else + { + if (v1y == v2y) + extralight = -contrast; + else if (v1x == v2x) + extralight = contrast; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } + } + + return (FUINT)finallight; +} + // // HWR_SplitWall // @@ -1044,19 +1084,20 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, float endpegt, endpegb, endpegmul; float endheight = 0.0f, endbheight = 0.0f; - fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); - fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo - fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); - fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; #endif - INT32 solid, i; + fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); + fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo + fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); + fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo + + INT32 solid, i; lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->FlatColor.s.alpha; - FUINT lightnum = sector->lightlevel; + FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; @@ -1086,12 +1127,12 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, { if (pfloor && (pfloor->flags & FF_FOG)) { - lightnum = pfloor->master->frontsector->lightlevel; + lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y); colormap = pfloor->master->frontsector->extra_colormap; } else { - lightnum = *list[i].lightlevel; + lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y); colormap = *list[i].extra_colormap; } } @@ -1395,7 +1436,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); } - lightnum = gr_frontsector->lightlevel; + lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = gr_frontsector->extra_colormap; if (gr_frontsector) @@ -2150,7 +2191,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; if (rover->master->frontsector->extra_colormap) @@ -2270,7 +2311,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; if (rover->master->frontsector->extra_colormap) @@ -6544,6 +6585,7 @@ static void HWR_FoggingOn(void) static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; +static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; static void CV_grmodellighting_OnChange(void); static void CV_grfiltermode_OnChange(void); @@ -6578,6 +6620,7 @@ consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_O consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grfov_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -6646,6 +6689,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grskydome); CV_RegisterVar(&cv_grspritebillboarding); + CV_RegisterVar(&cv_grfakecontrast); CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_grrounddown); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 573338226..20ff3ad9f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -99,6 +99,7 @@ extern consvar_t cv_grfovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grskydome; +extern consvar_t cv_grfakecontrast; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; From 65a02b0f8f4179ab28ddfdcbc0361fd75830cde6 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Wed, 25 Dec 2019 22:50:41 -0500 Subject: [PATCH 3/6] Increase precision of smooth contrast (cherry picked from commit 4c6664292e1f9b0d5c2ff34e28f05a8b63a4dd45) --- src/hardware/hw_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9f6e497a6..769aad5b7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1037,12 +1037,11 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t if (cv_grfakecontrast.value == 2) // Smooth setting { - extralight = -(contrast<>1)) >> FRACBITS; + * (contrast * 2)) >> FRACBITS; } else { From 15075d4e1be0ce830c7470bc8c0fd29df5d33753 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 29 Dec 2019 16:36:53 -0500 Subject: [PATCH 4/6] More blend image updates - Allow the translations that don't make use a blend image to work without requiring a blend image to be present - Fix TC_RAINBOW not working properly - TC_METALSONIC now remaps the _blend image to SKINCOLOR_COBALT, then inverts all of the blue, replicating how it works in Software (cherry picked from commit 74d7f256a7849d0c829177614b37089e2446f86b) --- src/hardware/hw_md2.c | 502 ++++++++++++++++++++++-------------------- 1 file changed, 260 insertions(+), 242 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 23145b525..099eaec4f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -654,12 +654,12 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; - UINT8 i; - UINT8 translation[16]; // First the color index UINT8 cutoff[16]; // Brightness cutoff before using the next color UINT8 translen = 0; + UINT8 i; + blendcolor = V_GetColor(0); // initialize memset(translation, 0, sizeof(translation)); memset(cutoff, 0, sizeof(cutoff)); @@ -685,7 +685,10 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap->grInfo.data; blendimage = blendgpatch->mipmap->grInfo.data; - blendcolor = V_GetColor(0); // initialize + + // TC_METALSONIC includes an actual skincolor translation, on top of its flashing. + if (skinnum == TC_METALSONIC) + color = SKINCOLOR_COBALT; if (color != SKINCOLOR_NONE) { @@ -721,7 +724,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, if (skinnum == TC_BOSS) { // Turn everything below a certain threshold white - if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue <= 82) + if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127) { // Lactozilla: Invert the colors cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); @@ -735,53 +738,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, cur->s.alpha = image->s.alpha; } - else if (skinnum == TC_METALSONIC) - { - // Turn everything below a certain blue threshold white - if (image->s.red == 0 && image->s.green == 0 && image->s.blue <= 82) - { - cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); - } - else - { - cur->s.red = image->s.red; - cur->s.green = image->s.green; - cur->s.blue = image->s.blue; - } - - cur->s.alpha = image->s.alpha; - } - else if (skinnum == TC_DASHMODE) - { - if (image->s.alpha == 0 && blendimage->s.alpha == 0) - { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 - cur->rgba = image->rgba; - } - else - { - UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha; - RGBA_t icolor = *image, bcolor; - - memset(&bcolor, 0x00, sizeof(RGBA_t)); - - if (blendimage->s.alpha) - { - bcolor.s.blue = 0; - bcolor.s.red = 255; - bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3; - } - if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic - { - icolor.s.red = image->s.blue; - icolor.s.blue = image->s.red; - } - cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255; - cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255; - cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255; - cur->s.alpha = image->s.alpha; - } - } else if (skinnum == TC_ALLWHITE) { // Turn everything white @@ -790,208 +746,268 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, } else { - UINT16 brightness; + // Everything below requires a blend image + if (blendimage == NULL) + { + cur->rgba = image->rgba; + goto skippixel; + } - I_Assert(translen > 0); - - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 - if (skinnum == TC_RAINBOW) + // Metal Sonic dash mode + if (skinnum == TC_DASHMODE) { if (image->s.alpha == 0 && blendimage->s.alpha == 0) { + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 cur->rgba = image->rgba; - cur++; image++; blendimage++; - continue; } else { - UINT16 imagebright, blendbright; - SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); - SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); - // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway - brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; + UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha; + RGBA_t icolor = *image, bcolor; + + memset(&bcolor, 0x00, sizeof(RGBA_t)); + + if (blendimage->s.alpha) + { + bcolor.s.blue = 0; + bcolor.s.red = 255; + bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3; + } + + if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic + { + icolor.s.red = image->s.blue; + icolor.s.blue = image->s.red; + } + + cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255; + cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255; + cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255; + cur->s.alpha = image->s.alpha; } } else { - if (blendimage->s.alpha == 0) + // All settings that use skincolors! + UINT16 brightness; + + if (translen <= 0) { cur->rgba = image->rgba; - cur++; image++; blendimage++; - continue; + goto skippixel; + } + + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + if (skinnum == TC_RAINBOW) + { + if (image->s.alpha == 0 && blendimage->s.alpha == 0) + { + cur->rgba = image->rgba; + goto skippixel; + } + else + { + UINT16 imagebright, blendbright; + SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); + SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); + // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway + brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; + } } else { - SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue); - } - } - - // Calculate a sort of "gradient" for the skincolor - // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) - { - RGBA_t nextcolor; - UINT8 firsti, secondi, mul, mulmax; - INT32 r, g, b; - - // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. - // Ensue horrible mess. - if (skinnum == TC_RAINBOW) - { - UINT16 brightdif = 256; - UINT8 colorbrightnesses[16]; - INT32 compare, m, d; - - // Ignore pure white & pitch black - if (brightness > 253 || brightness < 2) + if (blendimage->s.alpha == 0) { cur->rgba = image->rgba; - cur++; image++; blendimage++; - continue; + goto skippixel; // for metal sonic blend } - - firsti = 0; - mul = 0; - mulmax = 1; - - for (i = 0; i < translen; i++) + else { - RGBA_t tempc = V_GetColor(translation[i]); - SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison + SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue); } + } - for (i = 0; i < translen; i++) + // Calculate a sort of "gradient" for the skincolor + // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) + { + RGBA_t nextcolor; + UINT8 firsti, secondi, mul, mulmax; + INT32 r, g, b; + + // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. + // Ensue horrible mess. + if (skinnum == TC_RAINBOW) { - if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) - continue; + UINT16 brightdif = 256; + UINT8 colorbrightnesses[16]; + INT32 compare, m, d; - compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); - - if (compare < brightdif) + // Ignore pure white & pitch black + if (brightness > 253 || brightness < 2) { - brightdif = (UINT16)compare; - firsti = i; // best matching color that's equal brightness or darker + cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; } - } - secondi = firsti+1; // next color in line - if (secondi >= translen) - { - m = (INT16)brightness; // - 0; - d = (INT16)colorbrightnesses[firsti]; // - 0; - } - else - { - m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; - d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; - } - - if (m >= d) - m = d-1; - - // calculate the "gradient" multiplier based on how close this color is to the one next in line - if (m <= 0 || d <= 0) - { + firsti = 0; mul = 0; + mulmax = 1; + + for (i = 0; i < translen; i++) + { + RGBA_t tempc = V_GetColor(translation[i]); + SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison + } + + for (i = 0; i < translen; i++) + { + if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) + continue; + + compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); + + if (compare < brightdif) + { + brightdif = (UINT16)compare; + firsti = i; // best matching color that's equal brightness or darker + } + } + + secondi = firsti+1; // next color in line + if (secondi >= translen) + { + m = (INT16)brightness; // - 0; + d = (INT16)colorbrightnesses[firsti]; // - 0; + } + else + { + m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; + d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; + } + + if (m >= d) + m = d-1; + + mulmax = 16; + + // calculate the "gradient" multiplier based on how close this color is to the one next in line + if (m <= 0 || d <= 0) + mul = 0; + else + mul = (mulmax-1) - ((m * mulmax) / d); } else { + // Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler + firsti = 0; + + for (i = 1; i < translen; i++) + { + if (brightness >= cutoff[i]) + break; + firsti = i; + } + + secondi = firsti+1; + mulmax = cutoff[firsti]; if (secondi < translen) mulmax -= cutoff[secondi]; - mul = (mulmax-1) - ((m * mulmax) / d); + mul = cutoff[firsti] - brightness; } + + blendcolor = V_GetColor(translation[firsti]); + + if (mul > 0) // If it's 0, then we only need the first color. + { + if (secondi >= translen) // blend to black + nextcolor = V_GetColor(31); + else + nextcolor = V_GetColor(translation[secondi]); + + // Find difference between points + r = (INT32)(nextcolor.s.red - blendcolor.s.red); + g = (INT32)(nextcolor.s.green - blendcolor.s.green); + b = (INT32)(nextcolor.s.blue - blendcolor.s.blue); + + // Find the gradient of the two points + r = ((mul * r) / mulmax); + g = ((mul * g) / mulmax); + b = ((mul * b) / mulmax); + + // Add gradient value to color + blendcolor.s.red += r; + blendcolor.s.green += g; + blendcolor.s.blue += b; + } + } + + if (skinnum == TC_RAINBOW) + { + UINT32 tempcolor; + UINT16 colorbright; + + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + if (colorbright == 0) + colorbright = 1; // no dividing by 0 please + + tempcolor = (brightness * blendcolor.s.red) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.green) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.blue) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; } else { - // Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler - firsti = 0; + // Color strength depends on image alpha + INT32 tempcolor; - for (i = 1; i < translen; i++) + tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + +skippixel: + + // *Now* we can do Metal Sonic's flashing + if (skinnum == TC_METALSONIC) + { + // Blend dark blue into white + if (cur->s.alpha > 0 && cur->s.red == 0 && cur->s.green == 0 && cur->s.blue < 255 && cur->s.blue > 31) { - if (brightness >= cutoff[i]) - break; - firsti = i; + // Sal: Invert non-blue + cur->s.red = cur->s.green = (255 - cur->s.blue); + cur->s.blue = 255; } - secondi = firsti+1; - - mulmax = cutoff[firsti]; - if (secondi < translen) - mulmax -= cutoff[secondi]; - - mul = cutoff[firsti] - brightness; + cur->s.alpha = image->s.alpha; } - - blendcolor = V_GetColor(translation[firsti]); - - if (mul > 0) // If it's 0, then we only need the first color. - { - if (secondi >= translen) // blend to black - nextcolor = V_GetColor(31); - else - nextcolor = V_GetColor(translation[secondi]); - - // Find difference between points - r = (INT32)(nextcolor.s.red - blendcolor.s.red); - g = (INT32)(nextcolor.s.green - blendcolor.s.green); - b = (INT32)(nextcolor.s.blue - blendcolor.s.blue); - - // Find the gradient of the two points - r = ((mul * r) / mulmax); - g = ((mul * g) / mulmax); - b = ((mul * b) / mulmax); - - // Add gradient value to color - blendcolor.s.red += r; - blendcolor.s.green += g; - blendcolor.s.blue += b; - } - } - - if (skinnum == TC_RAINBOW) - { - UINT32 tempcolor; - UINT16 colorbright; - - SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); - if (colorbright == 0) - colorbright = 1; // no dividing by 0 please - - tempcolor = (brightness * blendcolor.s.red) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - - tempcolor = (brightness * blendcolor.s.green) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - - tempcolor = (brightness * blendcolor.s.blue) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; - } - else - { - // Color strength depends on image alpha - INT32 tempcolor; - - tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - - tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - - tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; } } - cur++; image++; blendimage++; + cur++; image++; + + if (blendimage != NULL) + blendimage++; } return; @@ -1030,6 +1046,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // If here, the blended texture has not been created // So we create it + if ((blendgpatch && blendgpatch->mipmap->grInfo.format) + && (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height)) + { + // Blend image exists, but it's bad. + HWD.pfnSetTexture(gpatch->mipmap); + return; + } + //BP: WARNING: don't free it manually without clearing the cache of harware renderer // (it have a liste of mipmap) // this malloc is cleared in HWR_FreeTextureCache @@ -1273,50 +1297,44 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture { - if (md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format - && gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height) - { - INT32 skinnum = INT32_MAX; - if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" - { - if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) - skinnum = TC_ALLWHITE; - else if (spr->mobj->type == MT_METALSONIC_BATTLE) - skinnum = TC_METALSONIC; - else - skinnum = TC_BOSS; - } - else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE) - { - if (spr->mobj->colorized) - skinnum = TC_RAINBOW; - else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (spr->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (spr->mobj->player->charflags & SF_MACHINE) - skinnum = TC_DASHMODE; - else - skinnum = TC_RAINBOW; - } - else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); - else - skinnum = TC_DEFAULT; - } + INT32 skinnum = INT32_MAX; - // Translation or skin number found - if (skinnum != INT32_MAX) - HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color); + if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" + { + if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) + skinnum = TC_ALLWHITE; + else if (spr->mobj->type == MT_METALSONIC_BATTLE) + skinnum = TC_METALSONIC; else + skinnum = TC_BOSS; + } + else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE) + { + if (spr->mobj->colorized) + skinnum = TC_RAINBOW; + else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (spr->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) { - // Sorry nothing - HWD.pfnSetTexture(gpatch->mipmap); + if (spr->mobj->player->charflags & SF_MACHINE) + skinnum = TC_DASHMODE; + else + skinnum = TC_RAINBOW; } + else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); + else + skinnum = TC_DEFAULT; + } + + // Translation or skin number found + if (skinnum != INT32_MAX) + { + HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color); } else { - // This is safe, since we know the texture has been downloaded + // Sorry nothing HWD.pfnSetTexture(gpatch->mipmap); } } From d49cd9755bdb11b7037a3fe906c322df22225180 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Wed, 8 Jan 2020 04:10:23 -0500 Subject: [PATCH 5/6] Fullbright transparent planes (I disagree with this feature so hard but w/e) (cherry picked from commit fe809b2734d430655966151e56f96963e2d7b2cf) --- src/hardware/hw_main.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 769aad5b7..50b6fcbf5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5158,7 +5158,12 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = lightlevel; + + if (planecolormap && (planecolormap->fog & 1)) + planeinfo[numplanes].lightlevel = lightlevel; + else + planeinfo[numplanes].lightlevel = 255; + planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; @@ -5190,7 +5195,12 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = lightlevel; + + if (planecolormap && (planecolormap->fog & 1)) + polyplaneinfo[numpolyplanes].lightlevel = lightlevel; + else + polyplaneinfo[numpolyplanes].lightlevel = 255; + polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; From 487e1b02f1fb3b3b018390c5505775c10d371e1f Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Thu, 9 Jan 2020 01:28:14 -0500 Subject: [PATCH 6/6] Remove smooth setting It got denied before for Software so I won't include it in the merge request :( --- src/hardware/hw_main.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 50b6fcbf5..9bfd75edc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1035,21 +1035,10 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t const UINT8 contrast = 8; fixed_t extralight = 0; - if (cv_grfakecontrast.value == 2) // Smooth setting - { - extralight = (-(contrast<> FRACBITS; - } - else - { - if (v1y == v2y) - extralight = -contrast; - else if (v1x == v2x) - extralight = contrast; - } + if (v1y == v2y) + extralight = -contrast; + else if (v1x == v2x) + extralight = contrast; if (extralight != 0) { @@ -6594,7 +6583,6 @@ static void HWR_FoggingOn(void) static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; -static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; static void CV_grmodellighting_OnChange(void); static void CV_grfiltermode_OnChange(void); @@ -6629,7 +6617,7 @@ consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_O consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grfov_OnChange, 0, NULL, NULL, 0, 0, NULL};