2019-10-20 06:07:12 +00:00
/*
* * gl_texture . cpp
* * high level GL texture interface
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 2019 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 .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
* *
*/
2019-10-20 06:02:45 +00:00
# include "palette.h"
2013-05-15 02:17:17 +00:00
# include "build.h"
# include "hightile.h"
# include "polymost.h"
2019-10-10 21:29:13 +00:00
# include "textures.h"
# include "bitmap.h"
2019-11-05 22:35:38 +00:00
# include "v_font.h"
2020-05-23 12:40:54 +00:00
# include "palettecontainer.h"
2019-10-10 21:29:13 +00:00
# include "../../glbackend/glbackend.h"
2019-03-01 08:51:50 +00:00
2019-10-23 19:11:37 +00:00
// Test CVARs.
2020-01-25 18:10:05 +00:00
CVAR ( Int , fixpalette , - 1 , 0 )
CVAR ( Int , fixpalswap , - 1 , 0 )
2019-10-17 22:20:27 +00:00
template < class T >
void FlipNonSquareBlock ( T * dst , const T * src , int x , int y , int srcpitch )
{
for ( int i = 0 ; i < x ; + + i )
2019-10-17 19:44:34 +00:00
{
2019-10-17 22:20:27 +00:00
for ( int j = 0 ; j < y ; + + j )
2019-10-17 19:44:34 +00:00
{
2019-10-17 22:20:27 +00:00
dst [ i * y + j ] = src [ i + j * srcpitch ] ;
}
}
}
2019-10-17 19:44:34 +00:00
2017-06-27 02:24:34 +00:00
2019-10-17 22:20:27 +00:00
//===========================================================================
//
// Create an indexed version of the requested texture
//
//===========================================================================
2019-10-17 19:44:34 +00:00
2019-10-18 09:37:07 +00:00
FHardwareTexture * GLInstance : : CreateIndexedTexture ( FTexture * tex )
2019-10-17 22:20:27 +00:00
{
auto siz = tex - > GetSize ( ) ;
2019-10-17 19:44:34 +00:00
2019-10-17 22:20:27 +00:00
const uint8_t * p = tex - > Get8BitPixels ( ) ;
TArray < uint8_t > store ( siz . x * siz . y , true ) ;
if ( ! p )
{
tex - > Create8BitPixels ( store . Data ( ) ) ;
p = store . Data ( ) ;
2019-10-17 19:44:34 +00:00
}
2019-10-17 22:20:27 +00:00
auto glpic = GLInterface . NewTexture ( ) ;
2019-10-19 21:14:36 +00:00
glpic - > CreateTexture ( siz . x , siz . y , FHardwareTexture : : Indexed , false ) ;
2019-10-17 22:20:27 +00:00
TArray < uint8_t > flipped ( siz . x * siz . y , true ) ;
FlipNonSquareBlock ( flipped . Data ( ) , p , siz . y , siz . x , siz . y ) ;
glpic - > LoadTexture ( flipped . Data ( ) ) ;
return glpic ;
}
//===========================================================================
2019-10-18 09:37:07 +00:00
//
// Create a true color version of the requested tile
2019-10-17 22:20:27 +00:00
//
//===========================================================================
2019-10-19 21:14:36 +00:00
FHardwareTexture * GLInstance : : CreateTrueColorTexture ( FTexture * tex , int palid , bool checkfulltransparency , bool rgb8bit )
2019-10-17 22:20:27 +00:00
{
2019-10-18 09:37:07 +00:00
auto palette = palid < 0 ? nullptr : palmanager . GetPaletteData ( palid ) ;
2019-12-01 20:43:54 +00:00
if ( palid > = 0 & & palette = = nullptr ) return nullptr ;
2020-02-18 19:43:16 +00:00
auto texbuffer = tex - > CreateTexBuffer ( palette , checkfulltransparency ? 0 : CTF_ProcessData ) ;
2019-10-18 09:37:07 +00:00
// Check if the texture is fully transparent. When creating a brightmap such textures can be discarded.
if ( checkfulltransparency )
2019-10-17 19:44:34 +00:00
{
2019-10-18 09:37:07 +00:00
int siz = texbuffer . mWidth * texbuffer . mHeight * 4 ;
bool found = false ;
for ( int i = 3 ; i < siz ; i + = 4 )
2019-10-17 19:44:34 +00:00
{
2019-10-18 09:37:07 +00:00
if ( texbuffer . mBuffer [ i ] > 0 )
{
found = true ;
break ;
}
2019-10-17 19:44:34 +00:00
}
2019-10-18 09:37:07 +00:00
if ( ! found ) return nullptr ;
2019-10-17 19:44:34 +00:00
}
2019-10-18 09:37:07 +00:00
auto glpic = GLInterface . NewTexture ( ) ;
2019-10-19 21:14:36 +00:00
if ( ! rgb8bit )
glpic - > CreateTexture ( texbuffer . mWidth , texbuffer . mHeight , FHardwareTexture : : TrueColor , true ) ;
else
glpic - > CreateTexture ( texbuffer . mWidth , texbuffer . mHeight , FHardwareTexture : : Brightmap , false ) ; // Use a more memory friendly format for simple brightmaps.
2019-10-18 09:37:07 +00:00
glpic - > LoadTexture ( texbuffer . mBuffer ) ;
return glpic ;
}
//===========================================================================
//
// Retrieve the texture to be used.
//
//===========================================================================
FHardwareTexture * GLInstance : : LoadTexture ( FTexture * tex , int textype , int palid )
{
if ( textype = = TT_INDEXED ) palid = - 1 ;
auto phwtex = tex - > GetHardwareTexture ( palid ) ;
if ( phwtex ) return * phwtex ;
2020-03-29 12:01:46 +00:00
FHardwareTexture * hwtex = nullptr ;
2019-10-18 09:37:07 +00:00
if ( textype = = TT_INDEXED )
2019-10-18 17:06:57 +00:00
hwtex = CreateIndexedTexture ( tex ) ;
2020-05-24 14:11:10 +00:00
else if ( tex - > GetUseType ( ) ! = ETextureType : : Canvas )
2019-10-19 21:14:36 +00:00
hwtex = CreateTrueColorTexture ( tex , textype = = TT_HICREPLACE ? - 1 : palid , textype = = TT_BRIGHTMAP , textype = = TT_BRIGHTMAP ) ;
2020-03-29 12:01:46 +00:00
else
hwtex = nullptr ;
2019-10-18 09:37:07 +00:00
2019-11-10 18:42:26 +00:00
if ( hwtex ) tex - > SetHardwareTexture ( palid , hwtex ) ;
2019-10-18 09:37:07 +00:00
return hwtex ;
2019-10-17 22:20:27 +00:00
}
2019-10-17 19:44:34 +00:00
2019-10-17 22:20:27 +00:00
//===========================================================================
//
2019-10-18 12:04:32 +00:00
// Sets a texture for rendering. This should be the ONLY place to bind in-game textures
2019-10-17 22:20:27 +00:00
//
//===========================================================================
2019-10-17 19:44:34 +00:00
2020-05-23 12:40:54 +00:00
struct TexturePick
{
FTexture * texture ; // which texture to use
int translation ; // which translation table to use
int tintFlags ; // which shader tinting options to use
PalEntry tintColor ; // Tint color
PalEntry basepalTint ; // can the base palette be done with a global tint effect?
} ;
2020-05-24 06:47:45 +00:00
#if 0
2020-05-23 12:40:54 +00:00
TexturePick PickTexture ( int tilenum , int basepal , int palette )
{
TexturePick pick = { nullptr , 0 , - 1 , 0xffffff , 0xffffff } ;
int usepalette = fixpalette > = 0 ? fixpalette : basepal ;
int usepalswap = fixpalswap > = 0 ? fixpalswap : palette ;
auto & h = hictinting [ palette ] ;
auto tex = TileFiles . tiles [ tilenum ] ;
2020-05-24 06:47:45 +00:00
auto rep = ( hw_hightile & & ! ( h . f & HICTINT_ALWAYSUSEART ) ) ? TileFiles . FindReplacement ( tilenum , usepalswap ) : nullptr ;
2020-05-23 12:40:54 +00:00
// Canvas textures must be treated like hightile replacements in the following code.
bool truecolor = rep | | tex - > GetUseType ( ) = = FTexture : : Canvas ;
bool applytint = false ;
if ( truecolor )
{
if ( usepalette ! = 0 )
{
// This is a global setting for the entire scene, so let's do it here, right at the start. (Fixme: Store this in a static table instead of reusing the same entry for all palettes.)
auto & hh = hictinting [ MAXPALOOKUPS - 1 ] ;
// This sets a tinting color for global palettes, e.g. water or slime - only used for hires replacements (also an option for low-resource hardware where duplicating the textures may be problematic.)
pick . basepalTint = hh . tint ;
}
if ( rep )
{
tex = rep - > faces [ 0 ] ;
}
if ( ! rep | | rep - > palnum ! = palette | | ( h . f & HICTINT_APPLYOVERALTPAL ) ) applytint = true ;
}
else
{
// Tinting is not used on indexed textures, unless explicitly requested
if ( h . f & ( HICTINT_ALWAYSUSEART | HICTINT_USEONART ) )
{
applytint = true ;
if ( ! ( h . f & HICTINT_APPLYOVERPALSWAP ) ) usepalswap = 0 ;
}
pick . translation = TRANSLATION ( usepalette + 1 , usepalswap ) ;
}
pick . texture = tex ;
if ( applytint & & h . f )
{
pick . tintFlags = h . f ;
pick . tintColor = h . tint ;
}
return pick ;
}
2020-05-24 06:47:45 +00:00
# endif
2020-05-23 12:40:54 +00:00
2020-01-18 21:41:08 +00:00
bool GLInstance : : SetTextureInternal ( int picnum , FTexture * tex , int palette , int method , int sampleroverride , FTexture * det , float detscale , FTexture * glow )
2019-10-17 22:20:27 +00:00
{
2020-05-24 06:47:45 +00:00
if ( tex - > GetTexelWidth ( ) < = 0 | | tex - > GetTexelHeight ( ) < = 0 ) return false ;
2020-01-25 18:10:05 +00:00
int usepalette = fixpalette > = 0 ? fixpalette : curbasepal ;
int usepalswap = fixpalswap > = 0 ? fixpalswap : palette ;
2019-10-17 22:20:27 +00:00
GLInterface . SetPalette ( usepalette ) ;
GLInterface . SetPalswap ( usepalswap ) ;
2019-12-30 19:44:37 +00:00
bool texbound [ 3 ] = { } ;
2020-01-18 21:41:08 +00:00
int MatrixChange = 0 ;
2019-10-17 19:44:34 +00:00
2020-02-04 19:40:10 +00:00
TextureType = hw_int_useindexedcolortextures ? TT_INDEXED : TT_TRUECOLOR ;
2019-10-17 19:44:34 +00:00
2019-10-17 22:20:27 +00:00
int lookuppal = 0 ;
VSMatrix texmat ;
2019-10-17 19:44:34 +00:00
2020-02-11 19:55:47 +00:00
GLInterface . SetBasepalTint ( 0xffffff ) ;
2020-01-11 21:18:06 +00:00
auto & h = hictinting [ palette ] ;
bool applytint = false ;
2020-03-29 12:01:46 +00:00
// Canvas textures must be treated like hightile replacements in the following code.
2020-05-24 08:30:09 +00:00
if ( picnum < 0 ) picnum = TileFiles . GetTileIndex ( tex ) ; // Allow getting replacements also when the texture is not passed by its tile number.
2020-05-24 06:47:45 +00:00
auto rep = ( picnum > = 0 & & hw_hightile & & ! ( h . f & HICTINT_ALWAYSUSEART ) ) ? TileFiles . FindReplacement ( picnum , palette ) : nullptr ;
2020-05-24 14:11:10 +00:00
if ( rep | | tex - > GetUseType ( ) = = ETextureType : : Canvas )
2019-10-17 22:20:27 +00:00
{
2020-02-11 19:55:47 +00:00
if ( usepalette ! = 0 )
{
// This is a global setting for the entire scene, so let's do it here, right at the start. (Fixme: Store this in a static table instead of reusing the same entry for all palettes.)
auto & hh = hictinting [ MAXPALOOKUPS - 1 ] ;
// This sets a tinting color for global palettes, e.g. water or slime - only used for hires replacements (also an option for low-resource hardware where duplicating the textures may be problematic.)
GLInterface . SetBasepalTint ( hh . tint ) ;
}
2020-03-29 12:01:46 +00:00
if ( rep )
{
tex = rep - > faces [ 0 ] ;
}
if ( ! rep | | rep - > palnum ! = palette | | ( h . f & HICTINT_APPLYOVERALTPAL ) ) applytint = true ;
2019-10-17 22:20:27 +00:00
TextureType = TT_HICREPLACE ;
}
else
{
// Only look up the palette if we really want to use it (i.e. when creating a true color texture of an ART tile.)
2019-11-10 18:42:26 +00:00
if ( TextureType = = TT_TRUECOLOR )
{
2020-01-11 21:18:06 +00:00
// Tinting is not used on indexed textures
if ( h . f & ( HICTINT_ALWAYSUSEART | HICTINT_USEONART ) )
{
applytint = true ;
if ( ! ( h . f & HICTINT_APPLYOVERPALSWAP ) ) usepalswap = 0 ;
}
2020-05-23 12:36:35 +00:00
lookuppal = palmanager . LookupPalette ( usepalette , usepalswap , false , 0 ) ;
2019-11-10 18:42:26 +00:00
}
2019-10-17 22:20:27 +00:00
}
2019-10-17 19:44:34 +00:00
2020-01-11 21:18:06 +00:00
// This is intentionally the same value for both parameters. The shader does not use the same uniform for modulation and overlay colors.
2020-02-05 19:02:50 +00:00
if ( applytint & & h . f )
GLInterface . SetTinting ( h . f , h . tint , h . tint ) ;
2020-01-11 21:18:06 +00:00
else GLInterface . SetTinting ( - 1 , 0xffffff , 0xffffff ) ;
2019-10-17 22:20:27 +00:00
// Load the main texture
auto mtex = LoadTexture ( tex , TextureType , lookuppal ) ;
if ( mtex )
{
2019-10-19 18:25:58 +00:00
auto sampler = ( method & DAMETH_CLAMPED ) ? ( sampleroverride ! = - 1 ? sampleroverride : SamplerClampXY ) : SamplerRepeat ;
2019-10-19 22:31:27 +00:00
if ( TextureType = = TT_INDEXED )
{
sampler = sampler + SamplerNoFilterRepeat - SamplerRepeat ;
}
2019-12-30 19:44:37 +00:00
UseDetailMapping ( false ) ;
UseGlowMapping ( false ) ;
2019-11-10 18:42:26 +00:00
UseBrightmaps ( false ) ;
2019-10-17 19:44:34 +00:00
2019-10-17 22:20:27 +00:00
BindTexture ( 0 , mtex , sampler ) ;
2020-01-18 21:41:08 +00:00
// Needs a) testing and b) verification for correctness. This doesn't look like it makes sense.
if ( rep & & ( rep - > scale . x ! = 1.0f | | rep - > scale . y ! = 1.0f ) )
2019-10-17 22:20:27 +00:00
{
2020-01-18 21:41:08 +00:00
//texmat.loadIdentity();
//texmat.scale(rep->scale.x, rep->scale.y, 1.0f);
//GLInterface.SetMatrix(Matrix_Texture, &texmat);
2019-10-17 22:20:27 +00:00
}
2019-10-17 19:44:34 +00:00
2019-10-17 22:20:27 +00:00
// Also load additional layers needed for this texture.
2020-05-24 08:30:09 +00:00
if ( hw_detailmapping & & hw_hightile & & picnum > - 1 )
2019-10-17 22:20:27 +00:00
{
2019-10-18 12:04:32 +00:00
float detscalex = detscale , detscaley = detscale ;
if ( ! ( method & DAMETH_MODEL ) )
2019-10-17 22:20:27 +00:00
{
2020-05-24 06:47:45 +00:00
auto drep = TileFiles . FindReplacement ( picnum , DETAILPAL ) ;
2019-10-18 12:04:32 +00:00
if ( drep )
{
det = drep - > faces [ 0 ] ;
detscalex = drep - > scale . x ;
detscaley = drep - > scale . y ;
}
}
if ( det )
{
auto htex = LoadTexture ( det , TT_HICREPLACE , 0 ) ;
2019-10-17 22:20:27 +00:00
UseDetailMapping ( true ) ;
BindTexture ( 3 , htex , SamplerRepeat ) ;
2019-12-30 19:44:37 +00:00
texbound [ 0 ] = true ;
2019-10-17 22:20:27 +00:00
2020-01-18 21:41:08 +00:00
/* todo: instead of a matrix, just pass a two-component uniform. Using a full matrix here is problematic.
2019-10-18 12:04:32 +00:00
if ( MatrixChange & 1 ) MatrixChange | = 2 ;
else texmat . loadIdentity ( ) ;
if ( ( detscalex ! = 1.0f ) | | ( detscaley ! = 1.0f ) )
2019-10-17 22:20:27 +00:00
{
2019-10-18 12:04:32 +00:00
texmat . scale ( detscalex , detscaley , 1.0f ) ;
2019-10-17 22:20:27 +00:00
MatrixChange | = 2 ;
}
if ( MatrixChange & 2 ) GLInterface . SetMatrix ( Matrix_Detail , & texmat ) ;
2020-01-18 21:41:08 +00:00
*/
2019-10-17 22:20:27 +00:00
}
}
2020-05-24 08:30:09 +00:00
if ( hw_glowmapping & & hw_hightile & & picnum > - 1 )
2019-10-17 22:20:27 +00:00
{
2019-10-18 12:04:32 +00:00
if ( ! ( method & DAMETH_MODEL ) )
2019-10-17 22:20:27 +00:00
{
2020-05-24 06:47:45 +00:00
auto drep = TileFiles . FindReplacement ( picnum , GLOWPAL ) ;
2019-10-18 12:04:32 +00:00
if ( drep )
{
glow = drep - > faces [ 0 ] ;
}
}
if ( glow )
{
auto htex = LoadTexture ( glow , TT_HICREPLACE , 0 ) ;
2019-10-17 22:20:27 +00:00
UseGlowMapping ( true ) ;
BindTexture ( 4 , htex , SamplerRepeat ) ;
2019-12-30 19:44:37 +00:00
texbound [ 1 ] = true ;
2019-10-17 22:20:27 +00:00
}
}
2019-11-15 19:51:02 +00:00
# if 1
2020-05-24 11:53:27 +00:00
if ( picnum > - 1 & & ! ( TileFiles . tiledata [ picnum ] . picanm . sf & PICANM_NOFULLBRIGHT_BIT ) & & ! ( globalflags & GLOBAL_NO_GL_FULLBRIGHT ) & & ! tex - > NoBrightmapFlag [ usepalswap ] )
2019-10-17 22:20:27 +00:00
{
2019-10-18 09:37:07 +00:00
if ( TextureType = = TT_HICREPLACE )
{
2020-05-24 06:47:45 +00:00
auto brep = TileFiles . FindReplacement ( picnum , BRIGHTPAL ) ;
2019-10-18 09:37:07 +00:00
if ( brep )
{
2019-11-24 23:02:00 +00:00
LoadTexture ( brep - > faces [ 0 ] , TT_HICREPLACE , 0 ) ;
2019-11-10 18:42:26 +00:00
UseBrightmaps ( true ) ;
2019-10-18 09:37:07 +00:00
BindTexture ( 5 , mtex , sampler ) ;
2019-12-30 19:44:37 +00:00
texbound [ 2 ] = true ;
2019-10-18 09:37:07 +00:00
}
2019-11-10 18:42:26 +00:00
else
{
2020-05-24 11:53:27 +00:00
TileFiles . tiledata [ picnum ] . picanm . sf | = PICANM_NOFULLBRIGHT_BIT ;
2019-11-10 18:42:26 +00:00
}
2019-10-18 09:37:07 +00:00
}
else if ( TextureType = = TT_TRUECOLOR )
{
lookuppal = palmanager . LookupPalette ( usepalette , usepalswap , true ) ;
if ( lookuppal > = 0 )
{
auto htex = LoadTexture ( tex , TT_BRIGHTMAP , lookuppal ) ;
2019-11-10 18:42:26 +00:00
if ( htex = = nullptr )
{
// Flag the texture as not being brightmapped for the given palette
tex - > NoBrightmapFlag . Set ( usepalswap ) ;
}
else
{
UseBrightmaps ( true ) ;
2019-11-11 22:54:09 +00:00
BindTexture ( 5 , htex , sampler ) ;
2019-12-30 19:44:37 +00:00
texbound [ 2 ] = true ;
2019-11-10 18:42:26 +00:00
}
2019-10-18 09:37:07 +00:00
}
}
2019-10-17 22:20:27 +00:00
}
2019-12-30 19:44:37 +00:00
if ( ! texbound [ 0 ] ) UnbindTexture ( 3 ) ;
if ( ! texbound [ 1 ] ) UnbindTexture ( 4 ) ;
if ( ! texbound [ 2 ] ) UnbindTexture ( 5 ) ;
2019-11-15 19:51:02 +00:00
# endif
2019-10-17 22:20:27 +00:00
}
2019-10-18 17:06:57 +00:00
else return false ;
2019-10-17 19:44:34 +00:00
2019-10-19 22:31:27 +00:00
float al = 0.5f ;
2019-10-17 22:20:27 +00:00
if ( TextureType = = TT_HICREPLACE )
{
2019-10-19 08:21:07 +00:00
al = ( ( unsigned ) picnum < MAXTILES & & alphahackarray [ picnum ] ! = 0 ) ? alphahackarray [ picnum ] * ( 1.f / 255.f ) :
2019-11-10 09:01:31 +00:00
( tex - > alphaThreshold > = 0 ? tex - > alphaThreshold * ( 1.f / 255.f ) : 0.f ) ;
2019-10-17 22:20:27 +00:00
}
2019-10-17 19:44:34 +00:00
GLInterface . SetAlphaThreshold ( al ) ;
2019-10-18 17:06:57 +00:00
return true ;
2019-10-17 19:44:34 +00:00
}
2017-06-27 02:24:34 +00:00
2013-05-15 02:18:27 +00:00
2019-11-05 22:35:38 +00:00
//===========================================================================
//
// Sets a named texture for 2D rendering. In this case the palette is
// a direct index into the palette map.
//
//===========================================================================
bool GLInstance : : SetNamedTexture ( FTexture * tex , int palette , int sampler )
{
auto mtex = LoadTexture ( tex , palette > = 0 ? TT_TRUECOLOR : TT_HICREPLACE , palette ) ;
if ( ! mtex ) return false ;
BindTexture ( 0 , mtex , sampler ) ;
2019-11-10 09:01:31 +00:00
GLInterface . SetAlphaThreshold ( tex - > isTranslucent ( ) ? 0.f : 0.5f ) ;
2019-11-05 22:35:38 +00:00
return true ;
}