2020-06-07 11:35:23 +00:00
/*
* * palette . cpp
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 2019 - 2020 Christoph Oelckers
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
2018-11-05 07:28:01 +00:00
2016-06-21 00:33:06 +00:00
# include "build.h"
2020-01-28 09:31:59 +00:00
# include "imagehelpers.h"
2019-12-17 22:25:07 +00:00
2016-06-21 00:33:06 +00:00
# include "palette.h"
2019-11-02 21:52:13 +00:00
# include "superfasthash.h"
2019-10-10 22:34:27 +00:00
# include "common.h"
2020-04-12 05:50:24 +00:00
# include "memarena.h"
# include "palettecontainer.h"
2020-04-12 05:51:11 +00:00
# include "palutil.h"
# include "colormatcher.h"
2020-05-23 12:40:54 +00:00
# include "m_swap.h"
2020-05-24 19:19:33 +00:00
# include "v_colortables.h"
2020-04-05 20:51:53 +00:00
# include "v_font.h"
2019-09-16 19:08:42 +00:00
# include "../../glbackend/glbackend.h"
2016-06-21 00:33:06 +00:00
2020-05-27 20:19:02 +00:00
LookupTableInfo lookups ;
2020-04-12 05:50:24 +00:00
2020-05-23 12:40:54 +00:00
//==========================================================================
//
// Adds a palette to the global list of base palettes
//
//==========================================================================
2019-11-10 14:15:14 +00:00
2020-05-23 12:40:54 +00:00
void paletteSetColorTable ( int32_t id , uint8_t const * table , bool notransparency , bool twodonly )
2020-04-12 05:50:24 +00:00
{
if ( id = = 0 )
{
GPalette . SetPalette ( table , 255 ) ;
2020-05-24 21:26:47 +00:00
GPalette . BaseColors [ 255 ] = 0 ;
2020-05-24 13:02:20 +00:00
BuildTransTable ( GPalette . BaseColors ) ;
2020-04-12 05:50:24 +00:00
}
FRemapTable remap ;
2020-06-28 19:38:25 +00:00
remap . AddColors ( 0 , 256 , table , - 1 ) ;
2020-04-12 05:50:24 +00:00
if ( ! notransparency )
{
remap . Palette [ 255 ] = 0 ;
remap . Remap [ 255 ] = 255 ;
}
2020-05-23 12:40:54 +00:00
remap . Inactive = twodonly ; // use Inactive as a marker for the postprocessing so that for pure 2D palettes the creation of shade tables can be skipped.
2020-04-12 05:50:24 +00:00
GPalette . UpdateTranslation ( TRANSLATION ( Translation_BasePalettes , id ) , & remap ) ;
}
2020-05-23 12:40:54 +00:00
//==========================================================================
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
// loads the main palette file.
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
//==========================================================================
2018-04-12 21:03:12 +00:00
void paletteLoadFromDisk ( void )
2016-06-21 00:33:06 +00:00
{
2018-10-25 23:33:40 +00:00
for ( auto & x : glblend )
x = defaultglblend ;
2019-09-19 20:02:45 +00:00
2020-04-11 21:54:33 +00:00
auto fil = fileSystem . OpenFileReader ( " palette.dat " ) ;
2019-10-20 22:13:17 +00:00
if ( ! fil . isOpen ( ) )
2016-06-21 00:33:06 +00:00
return ;
2020-05-29 18:15:42 +00:00
// Base palette
2020-04-12 05:51:11 +00:00
uint8_t palette [ 768 ] ;
2019-10-20 22:13:17 +00:00
if ( 768 ! = fil . Read ( palette , 768 ) )
return ;
2016-06-21 00:33:06 +00:00
2020-06-07 11:06:18 +00:00
for ( auto & pe : palette )
pe < < = 2 ;
2016-06-21 00:33:06 +00:00
2020-05-23 12:40:54 +00:00
paletteSetColorTable ( 0 , palette , false , false ) ;
2016-06-21 00:33:06 +00:00
paletteloaded | = PALETTE_MAIN ;
2020-05-29 18:15:42 +00:00
// LameDuke and Witchaven use an older variant.
if ( fil . GetLength ( ) = = 41600 )
2016-06-21 00:33:06 +00:00
{
2020-05-29 18:15:42 +00:00
numshades = 32 ;
2020-05-23 12:40:54 +00:00
}
else
{
2020-05-29 18:15:42 +00:00
// Shade tables
numshades = fil . ReadInt16 ( ) ;
if ( numshades < = 1 )
2016-06-21 00:33:06 +00:00
{
2020-05-29 18:15:42 +00:00
Printf ( " Warning: Invalid number of shades in \" palette.dat \" ! \n " ) ;
numshades = 0 ;
return ;
2016-06-21 00:33:06 +00:00
}
}
2020-04-12 05:48:23 +00:00
// Read base shade table (lookuptables 0).
2020-05-23 12:40:54 +00:00
int length = numshades * 256 ;
2020-05-23 16:18:36 +00:00
auto buffer = fil . Read ( length ) ;
if ( buffer . Size ( ) ! = length ) return ;
2020-05-27 20:19:02 +00:00
lookups . setTable ( 0 , buffer . Data ( ) ) ;
2016-06-21 00:33:06 +00:00
2020-06-11 07:15:44 +00:00
paletteloaded | = PALETTE_SHADE | PALETTE_TRANSLUC ;
2016-06-21 00:33:06 +00:00
}
2020-05-23 12:40:54 +00:00
//==========================================================================
//
// postprocess the palette data after everything has been loaded
//
//==========================================================================
2016-06-21 00:33:06 +00:00
2020-05-27 20:19:02 +00:00
void LookupTableInfo : : postLoadTables ( void )
2016-06-21 00:33:06 +00:00
{
globalpal = 0 ;
2020-05-27 20:19:02 +00:00
GPalette . GenerateGlobalBrightmapFromColormap ( getTable ( 0 ) , numshades ) ;
2016-06-21 00:33:06 +00:00
2020-05-27 20:19:02 +00:00
// Try to detect fullbright translations. Unfortunately this cannot be used to detect fade strength because of loss of color precision in the palette map.
for ( int j = 0 ; j < MAXPALOOKUPS ; j + + )
2016-06-21 00:33:06 +00:00
{
2020-05-27 20:19:02 +00:00
auto lookup = tables [ j ] . Shades ;
if ( lookup . Len ( ) > 0 )
2020-05-23 12:40:54 +00:00
{
2020-05-27 20:19:02 +00:00
auto basetable = ( uint8_t * ) lookup . GetChars ( ) ;
auto midtable = basetable + ( ( numshades / 2 ) - 1 ) * 256 ;
int lumibase = 0 , lumimid = 0 ;
for ( int i = 1 ; i < 255 ; i + + ) // intentionally leave out 0 and 255, because the table here is not translucency adjusted to the palette.
{
lumibase + = GPalette . BaseColors [ basetable [ i ] ] . Amplitude ( ) ;
lumimid + = GPalette . BaseColors [ midtable [ i ] ] . Amplitude ( ) ;
}
float divider = float ( lumimid ) / float ( lumibase ) ;
bool isbright = false ;
if ( divider > 0.9 )
{
2020-06-05 21:18:21 +00:00
tables [ j ] . ShadeFactor = 1 / 10000.f ; // this translation is fullbright.
2020-05-27 20:19:02 +00:00
}
else
{
2020-06-05 21:18:21 +00:00
if ( tables [ j ] . ShadeFactor = = 0 ) tables [ j ] . ShadeFactor = 1.f ;
2020-05-27 20:19:02 +00:00
// Fullbright lookups do not need brightmaps.
auto fog = tables [ j ] . FadeColor ;
if ( GPalette . HasGlobalBrightmap & & fog . r = = 0 & & fog . g = = 0 & & fog . b = = 0 )
{
isbright = true ;
// A translation is fullbright only if all fullbright colors in the base table are mapped to another fullbright color.
auto brightmap = GPalette . GlobalBrightmap . Remap ;
for ( int i = 1 ; i < 255 ; i + + ) // This also ignores entries 0 and 255 for the same reason as above.
{
int map = basetable [ i ] ;
if ( brightmap [ i ] = = GPalette . WhiteIndex & & brightmap [ map ] ! = GPalette . WhiteIndex )
{
isbright = false ;
break ;
}
}
}
}
tables [ j ] . hasBrightmap = isbright ;
DPrintf ( DMSG_NOTIFY , " Lookup %d is %sbright \n " , j , isbright ? " " : " not " ) ;
2020-05-23 12:40:54 +00:00
}
2016-06-21 00:33:06 +00:00
}
}
2020-05-23 12:40:54 +00:00
//==========================================================================
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
// load the lookup tables from lookup.dat
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
//==========================================================================
2020-05-27 20:19:02 +00:00
int32_t LookupTableInfo : : loadTable ( FileReader & fp )
2016-06-21 00:33:06 +00:00
{
2020-06-07 11:06:18 +00:00
uint8_t buffer [ 256 ] ;
2020-05-23 12:40:54 +00:00
int numlookups = fp . ReadUInt8 ( ) ;
if ( numlookups < 1 )
2016-06-21 00:33:06 +00:00
return - 1 ;
2020-05-23 12:40:54 +00:00
for ( int j = 0 ; j < numlookups ; j + + )
2016-06-21 00:33:06 +00:00
{
2020-05-23 12:40:54 +00:00
int palnum = fp . ReadUInt8 ( ) ;
2016-06-21 00:33:06 +00:00
2020-06-07 11:06:18 +00:00
if ( 256 ! = fp . Read ( buffer , 256 ) )
2016-06-21 00:33:06 +00:00
return - 1 ;
2020-06-07 11:06:18 +00:00
if ( palnum < 0 | | palnum > = 256 - RESERVEDPALS )
2016-06-21 00:33:06 +00:00
{
2020-06-07 11:06:18 +00:00
Printf ( " ERROR: attempt to load lookup at invalid index %d \n " , palnum ) ;
2016-06-21 00:33:06 +00:00
}
2020-05-23 12:40:54 +00:00
else
2020-06-07 11:06:18 +00:00
makeTable ( palnum , buffer , 0 , 0 , 0 , 0 ) ;
2016-06-21 00:33:06 +00:00
}
return 0 ;
}
2020-05-23 12:40:54 +00:00
//==========================================================================
//
// Find a gap of four consecutive unused pal numbers to generate fog shade tables.
//
//==========================================================================
2020-05-27 20:19:02 +00:00
void LookupTableInfo : : setupDefaultFog ( void )
2016-06-21 00:33:06 +00:00
{
2020-05-23 12:40:54 +00:00
for ( int j = 1 ; j < = 255 - 3 ; j + + )
{
2020-05-27 20:19:02 +00:00
if ( tables [ j ] . Shades . IsEmpty ( ) & & tables [ j + 1 ] . Shades . IsEmpty ( ) & & tables [ j + 2 ] . Shades . IsEmpty ( ) & & tables [ j + 3 ] . Shades . IsEmpty ( ) )
2016-06-21 00:33:06 +00:00
{
2020-05-27 20:19:02 +00:00
makeTable ( j , NULL , 60 , 60 , 60 , 1 ) ;
makeTable ( j + 1 , NULL , 60 , 0 , 0 , 1 ) ;
makeTable ( j + 2 , NULL , 0 , 60 , 0 , 1 ) ;
makeTable ( j + 3 , NULL , 0 , 0 , 60 , 1 ) ;
2016-06-21 00:33:06 +00:00
break ;
}
}
}
2020-05-23 12:40:54 +00:00
//==========================================================================
//
// post process the lookup tables once everything has been loaded
//
//==========================================================================
2016-10-09 07:55:23 +00:00
2020-05-27 20:19:02 +00:00
void LookupTableInfo : : postLoadLookups ( )
2019-12-29 20:36:21 +00:00
{
2020-05-23 12:40:54 +00:00
int numpalettes = GPalette . NumTranslations ( Translation_BasePalettes ) ;
if ( numpalettes = = 0 ) return ;
auto basepalette = GPalette . GetTranslation ( Translation_BasePalettes , 0 ) ;
2016-10-09 07:55:23 +00:00
2020-05-24 22:46:46 +00:00
for ( int i = 0 ; i < numpalettes ; i + + )
2019-12-29 20:36:21 +00:00
{
2020-05-24 22:46:46 +00:00
auto palette = GPalette . GetTranslation ( Translation_BasePalettes , i ) ;
if ( ! palette ) continue ;
if ( palette - > Inactive )
{
palette - > Inactive = false ;
GPalette . CopyTranslation ( TRANSLATION ( Translation_Remap + i , 0 ) , TRANSLATION ( Translation_BasePalettes , i ) ) ;
}
else
2020-05-23 12:40:54 +00:00
{
2020-05-24 22:46:46 +00:00
for ( int l = 0 ; l < MAXPALOOKUPS ; l + + )
2020-05-23 12:40:54 +00:00
{
2020-05-27 20:19:02 +00:00
if ( ! tables [ l ] . Shades . IsEmpty ( ) )
2020-05-23 12:40:54 +00:00
{
2020-05-27 20:19:02 +00:00
const uint8_t * lookup = ( uint8_t * ) tables [ l ] . Shades . GetChars ( ) ;
2020-05-24 22:46:46 +00:00
FRemapTable remap ;
if ( i = = 0 | | ( palette ! = basepalette & & ! palette - > Inactive ) )
2020-05-23 12:40:54 +00:00
{
2020-05-24 22:46:46 +00:00
memcpy ( remap . Remap , lookup , 256 ) ;
for ( int j = 0 ; j < 256 ; j + + )
{
remap . Palette [ j ] = palette - > Palette [ remap . Remap [ j ] ] ;
}
remap . NumEntries = 256 ;
GPalette . UpdateTranslation ( TRANSLATION ( i + Translation_Remap , l ) , & remap ) ;
2020-05-23 12:40:54 +00:00
}
2020-05-24 22:46:46 +00:00
if ( palette ! = basepalette ) palette - > Inactive = false ; // clear the marker flag
2020-05-23 12:40:54 +00:00
}
}
}
2019-12-29 20:36:21 +00:00
}
2020-05-24 21:26:47 +00:00
2020-06-28 19:38:25 +00:00
// Swap colors 0 and 255. Note that color 255 may not be translucent!
2020-05-24 21:26:47 +00:00
auto colorswap = [ ] ( FRemapTable * remap )
{
2020-06-28 19:38:25 +00:00
std : : swap ( remap - > Palette [ 255 ] , remap - > Palette [ 0 ] ) ;
std : : swap ( remap - > Remap [ 255 ] , remap - > Remap [ 0 ] ) ;
2020-05-24 21:26:47 +00:00
for ( auto & c : remap - > Remap )
{
if ( c = = 0 ) c = 255 ;
else if ( c = = 255 ) c = 0 ;
}
2020-05-27 20:19:02 +00:00
remap - > Remap [ 0 ] = 0 ;
2020-05-24 21:26:47 +00:00
} ;
for ( auto remap : GPalette . uniqueRemaps )
{
2020-04-05 20:51:53 +00:00
if ( ! remap - > ForFont ) colorswap ( remap ) ;
2020-05-24 21:26:47 +00:00
}
colorswap ( & GPalette . GlobalBrightmap ) ;
std : : swap ( GPalette . BaseColors [ 0 ] , GPalette . BaseColors [ 255 ] ) ;
2016-10-09 07:55:23 +00:00
}
2019-12-29 20:36:21 +00:00
2020-05-23 12:40:54 +00:00
//==========================================================================
//
// set a lookup table from external data
//
//==========================================================================
2016-10-09 07:55:23 +00:00
2020-05-27 20:19:02 +00:00
int32_t LookupTableInfo : : setTable ( int palnum , const uint8_t * shtab )
2016-06-21 00:33:06 +00:00
{
if ( shtab ! = NULL )
{
2020-05-23 12:40:54 +00:00
int length = numshades * 256 ;
2020-05-27 20:19:02 +00:00
tables [ palnum ] . Shades = FString ( ( const char * ) shtab , length ) ;
2016-06-21 00:33:06 +00:00
}
return 0 ;
}
2018-04-12 21:03:12 +00:00
2020-05-23 12:40:54 +00:00
//==========================================================================
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
// creates a lookup table from scratch
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
//==========================================================================
2020-05-27 20:19:02 +00:00
void LookupTableInfo : : makeTable ( int palnum , const uint8_t * remapbuf , int r , int g , int b , bool noFloorPal )
2016-06-21 00:33:06 +00:00
{
2020-05-23 16:18:36 +00:00
uint8_t idmap [ 256 ] ;
2016-06-21 00:33:06 +00:00
// NOTE: palnum==0 is allowed
2020-05-23 12:40:54 +00:00
if ( paletteloaded = = 0 | | ( unsigned ) palnum > = MAXPALOOKUPS )
2016-06-21 00:33:06 +00:00
return ;
2020-05-27 20:19:02 +00:00
tables [ palnum ] . noFloorPal = noFloorPal ;
2016-06-21 00:33:06 +00:00
2020-05-23 12:40:54 +00:00
if ( remapbuf = = nullptr )
2016-06-21 00:33:06 +00:00
{
2020-06-07 11:35:23 +00:00
if ( r = = 0 & & g = = 0 & & b = = 0 )
2016-06-21 00:33:06 +00:00
{
2020-05-27 20:19:02 +00:00
clearTable ( palnum ) ;
2016-06-21 00:33:06 +00:00
return ;
}
2020-05-23 12:40:54 +00:00
for ( int i = 0 ; i < 256 ; i + + ) idmap [ i ] = i ;
2016-06-21 00:33:06 +00:00
remapbuf = idmap ;
}
2020-05-23 12:40:54 +00:00
int length = numshades * 256 ;
2020-05-27 20:19:02 +00:00
auto p = tables [ palnum ] . Shades . LockNewBuffer ( length ) ;
2020-06-07 10:51:26 +00:00
if ( r = = 0 & & g = = 0 & & b = = 0 )
2016-06-21 00:33:06 +00:00
{
// "black fog"/visibility case -- only remap color indices
2020-05-27 20:19:02 +00:00
auto src = getTable ( 0 ) ;
2020-05-23 12:40:54 +00:00
for ( int j = 0 ; j < numshades ; j + + )
for ( int i = 0 ; i < 256 ; i + + )
2016-06-21 00:33:06 +00:00
{
2020-05-23 12:40:54 +00:00
p [ 256 * j + i ] = src [ 256 * j + remapbuf [ i ] ] ;
2016-06-21 00:33:06 +00:00
}
}
else
{
// colored fog case
2020-05-23 12:40:54 +00:00
for ( int i = 0 ; i < numshades ; i + + )
2016-06-21 00:33:06 +00:00
{
2020-06-07 10:51:26 +00:00
int colfac = ( numshades - i ) ;
2020-05-23 12:40:54 +00:00
for ( int j = 0 ; j < 256 ; j + + )
2016-06-21 00:33:06 +00:00
{
2020-04-12 05:51:11 +00:00
PalEntry pe = GPalette . BaseColors [ remapbuf [ j ] ] ;
2020-06-07 10:51:26 +00:00
p [ 256 * i + j ] = ColorMatcher . Pick (
( pe . r * colfac + r * i ) / numshades ,
( pe . g * colfac + g * i ) / numshades ,
( pe . b * colfac + b * i ) / numshades ) ;
2016-06-21 00:33:06 +00:00
}
}
}
2020-05-27 20:19:02 +00:00
tables [ palnum ] . FadeColor . r = r ;
tables [ palnum ] . FadeColor . g = g ;
tables [ palnum ] . FadeColor . b = b ;
tables [ palnum ] . FadeColor . a = 1 ;
2016-06-21 00:33:06 +00:00
}
2020-05-23 12:40:54 +00:00
2020-05-29 18:15:42 +00:00
//==========================================================================
//
// hicsetpalettetint(pal,r,g,b,sr,sg,sb,effect)
// The tinting values represent a mechanism for emulating the effect of global sector
// palette shifts on true-colour textures and only true-colour textures.
// effect bitset: 1 = greyscale, 2 = invert
//
//==========================================================================
void LookupTableInfo : : setPaletteTint ( int palnum , int r , int g , int b , int sr , int sg , int sb , int flags )
{
if ( ( unsigned ) palnum > = MAXPALOOKUPS ) return ;
auto & lookup = tables [ palnum ] ;
lookup . tintColor = PalEntry ( r , g , b ) ;
lookup . tintShade = PalEntry ( sr , sg , sb ) ;
lookup . tintFlags = flags | TINTF_ENABLE ;
}
//==========================================================================
//
2020-06-11 16:40:53 +00:00
// todo: everything below belongs elsewhere. Move it out
2020-05-29 18:15:42 +00:00
//
//==========================================================================
2020-06-11 16:40:53 +00:00
# include "v_2ddrawer.h"
uint8_t curbasepal ;
PalEntry palfadergb ;
static int32_t tint_blood_r = 0 , tint_blood_g = 0 , tint_blood_b = 0 ;
glblend_t glblend [ MAXBLENDTABS ] ;
2020-05-29 18:15:42 +00:00
2020-06-21 21:46:17 +00:00
void videoSetPalette ( int palid , ESetPalFlags flags )
2020-05-23 12:40:54 +00:00
{
curbasepal = ( GPalette . GetTranslation ( Translation_BasePalettes , palid ) = = nullptr ) ? 0 : palid ;
if ( ( flags & Pal_DontResetFade ) = = 0 ) palfadergb = 0 ;
}
//==========================================================================
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
// map Build blend definitions to actual render style / alpha combos.
2016-06-21 00:33:06 +00:00
//
2020-05-23 12:40:54 +00:00
//==========================================================================
glblend_t const nullglblend =
2016-06-21 00:33:06 +00:00
{
2020-05-23 12:40:54 +00:00
{
{ 1.f , STYLEALPHA_One , STYLEALPHA_Zero , 0 } ,
{ 1.f , STYLEALPHA_One , STYLEALPHA_Zero , 0 } ,
} ,
} ;
glblend_t const defaultglblend =
{
{
{ 2.f / 3.f , STYLEALPHA_Src , STYLEALPHA_InvSrc , 0 } ,
{ 1.f / 3.f , STYLEALPHA_Src , STYLEALPHA_InvSrc , 0 } ,
} ,
} ;
2019-10-10 18:28:41 +00:00
2020-01-26 09:58:00 +00:00
2020-05-23 12:40:54 +00:00
FRenderStyle GetRenderStyle ( int blend , int def )
{
FRenderStyle rs ;
rs . BlendOp = STYLEOP_Add ;
auto glbdef = & glblend [ blend ] . def [ def ] ;
rs . SrcAlpha = glbdef - > src ;
rs . DestAlpha = glbdef - > dst ;
rs . Flags = 0 ;
return rs ;
2016-06-21 00:33:06 +00:00
}
2020-05-23 12:40:54 +00:00
void SetRenderStyleFromBlend ( uint8_t enable , uint8_t blend , uint8_t def )
2016-06-21 00:33:06 +00:00
{
2020-05-23 12:40:54 +00:00
if ( ! enable )
{
GLInterface . SetRenderStyle ( LegacyRenderStyles [ STYLE_Translucent ] ) ;
return ;
}
auto rs = GetRenderStyle ( blend , def ) ;
GLInterface . SetRenderStyle ( rs ) ;
2016-06-21 00:33:06 +00:00
}
2020-04-12 05:44:55 +00:00
2020-05-23 12:40:54 +00:00
float GetAlphaFromBlend ( uint32_t method , uint32_t blend )
2020-04-12 05:44:55 +00:00
{
2020-05-23 12:40:54 +00:00
return method = = DAMETH_TRANS1 | | method = = DAMETH_TRANS2 ? glblend [ blend ] . def [ method - DAMETH_TRANS1 ] . alpha : 1.f ;
}
2020-06-11 16:40:53 +00:00
//==========================================================================
//
// Fullscreen blend effects
//
//==========================================================================
void DrawFullscreenBlends ( )
{
// These get prepended to the 2D drawer so they must be submitted in reverse order of drawing.
if ( tint_blood_r | tint_blood_g | tint_blood_b )
{
PalEntry color2 ( 255 , std : : max ( - tint_blood_r , 0 ) , std : : max ( - tint_blood_g , 0 ) , std : : max ( - tint_blood_b , 0 ) ) ;
twod - > AddColorOnlyQuad ( 0 , 0 , twod - > GetWidth ( ) , twod - > GetHeight ( ) , color2 , & LegacyRenderStyles [ STYLE_Subtract ] , true ) ;
PalEntry color ( 255 , std : : max ( tint_blood_r , 0 ) , std : : max ( tint_blood_g , 0 ) , std : : max ( tint_blood_b , 0 ) ) ;
twod - > AddColorOnlyQuad ( 0 , 0 , twod - > GetWidth ( ) , twod - > GetHeight ( ) , color , & LegacyRenderStyles [ STYLE_Add ] , true ) ;
}
if ( palfadergb . a > 0 )
{
twod - > AddColorOnlyQuad ( 0 , 0 , twod - > GetWidth ( ) , twod - > GetHeight ( ) , palfadergb , & LegacyRenderStyles [ STYLE_Translucent ] , true ) ;
}
}
void videoTintBlood ( int32_t r , int32_t g , int32_t b )
{
tint_blood_r = r ;
tint_blood_g = g ;
tint_blood_b = b ;
}