2014-06-01 17:55:23 +00:00
/*
2018-09-02 00:57:29 +00:00
* This file is part of the DXX - Rebirth project < https : //www.dxx-rebirth.com/>.
2014-06-01 17:55:23 +00:00
* It is copyright by its individual contributors , as recorded in the
* project ' s Git history . See COPYING . txt at the top level for license
* terms and a link to the Git history .
*/
2007-06-10 16:21:53 +00:00
/*
*
* Graphics support functions for OpenGL .
*
*/
2016-09-24 18:06:10 +00:00
# include "dxxsconf.h"
2015-03-22 04:16:49 +00:00
# include <stdexcept>
2016-01-09 16:38:10 +00:00
# include <tuple>
2008-04-06 20:23:28 +00:00
# ifdef _WIN32
2006-03-20 16:43:15 +00:00
# include <windows.h>
# include <stddef.h>
# endif
2007-06-10 16:21:53 +00:00
# if defined(__APPLE__) && defined(__MACH__)
# include <OpenGL/gl.h>
# include <OpenGL/glu.h>
# else
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES
2011-01-06 11:43:55 +00:00
# include <GLES/gl.h>
# else
2006-03-20 16:43:15 +00:00
# include <GL/gl.h>
# include <GL/glu.h>
2007-06-10 16:21:53 +00:00
# endif
2011-01-06 11:43:55 +00:00
# endif
2006-03-20 16:43:15 +00:00
# include <string.h>
# include <math.h>
2007-06-10 16:21:53 +00:00
# include <stdio.h>
2006-03-20 16:43:15 +00:00
# include "3d.h"
# include "piggy.h"
2013-03-03 01:03:33 +00:00
# include "common/3d/globvars.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 16:43:15 +00:00
# include "texmap.h"
# include "palette.h"
# include "rle.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2013-12-26 04:18:28 +00:00
# include "config.h"
2007-01-09 01:23:49 +00:00
# include "u_mem.h"
2007-06-10 16:21:53 +00:00
2006-03-20 16:43:15 +00:00
# include "segment.h"
# include "textures.h"
# include "texmerge.h"
# include "effects.h"
# include "weapon.h"
# include "powerup.h"
2007-06-10 16:21:53 +00:00
# include "laser.h"
# include "player.h"
2015-04-02 02:36:57 +00:00
# include "robot.h"
2006-03-20 16:43:15 +00:00
# include "gamefont.h"
2014-07-03 01:47:29 +00:00
# include "byteutil.h"
2008-01-29 14:49:54 +00:00
# include "internal.h"
2007-10-05 23:47:16 +00:00
# include "gauges.h"
2014-11-23 04:36:58 +00:00
# include "object.h"
2013-03-03 19:41:09 +00:00
# include "args.h"
2006-03-20 16:43:15 +00:00
2014-01-18 18:02:02 +00:00
# include "compiler-range_for.h"
2020-08-10 03:45:14 +00:00
# include "d_levelstate.h"
2020-05-22 02:40:26 +00:00
# include "d_zip.h"
2014-01-18 18:02:02 +00:00
# include "partial_range.h"
2012-11-11 22:12:51 +00:00
# include <algorithm>
2020-05-02 21:18:43 +00:00
# include <memory>
2020-05-02 21:18:42 +00:00
# include <utility>
2012-11-11 22:12:51 +00:00
using std : : max ;
2006-03-20 16:43:15 +00:00
//change to 1 for lots of spew.
#if 0
2018-06-08 04:04:05 +00:00
# define glmprintf(A) con_printf A
2006-03-20 16:43:15 +00:00
# else
2018-06-30 21:53:55 +00:00
# define glmprintf(A)
2006-03-20 16:43:15 +00:00
# endif
# ifndef M_PI
# define M_PI 3.14159
# endif
2016-01-09 16:38:10 +00:00
namespace {
template < unsigned G >
struct enable_ogl_client_state
{
enable_ogl_client_state ( ) noexcept
{
glEnableClientState ( G ) ;
}
~ enable_ogl_client_state ( ) noexcept
{
glDisableClientState ( G ) ;
}
} ;
template < typename T , unsigned . . . Gs >
using ogl_client_states = std : : tuple < T , enable_ogl_client_state < Gs > . . . > ;
2020-05-22 02:40:26 +00:00
template < typename T , std : : size_t N1 , std : : size_t N2 >
union flatten_array
{
std : : array < T , N1 * N2 > flat ;
std : : array < std : : array < T , N1 > , N2 > nested ;
static_assert ( sizeof ( flat ) = = sizeof ( nested ) , " array padding error " ) ;
} ;
2016-01-09 16:38:10 +00:00
}
2008-04-06 20:23:28 +00:00
# if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
2006-03-20 16:43:15 +00:00
# define cosf(a) cos(a)
# define sinf(a) sin(a)
# endif
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-13 18:00:48 +00:00
2014-08-05 02:33:10 +00:00
static std : : unique_ptr < GLubyte [ ] > texbuf ;
2006-03-20 16:43:15 +00:00
2013-08-04 22:24:33 +00:00
unsigned last_width = ~ 0u , last_height = ~ 0u ;
2006-03-20 16:43:15 +00:00
int GL_TEXTURE_2D_enabled = - 1 ;
2013-08-14 21:12:51 +00:00
static int r_texcount = 0 , r_cachedtexcount = 0 ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES
2013-08-14 21:12:51 +00:00
static int ogl_rgba_internalformat = GL_RGBA ;
static int ogl_rgb_internalformat = GL_RGB ;
2011-01-06 11:43:55 +00:00
# else
2013-08-14 21:12:51 +00:00
static int ogl_rgba_internalformat = GL_RGBA8 ;
static int ogl_rgb_internalformat = GL_RGB8 ;
2011-01-06 11:43:55 +00:00
# endif
2014-08-05 02:32:35 +00:00
static std : : unique_ptr < GLfloat [ ] > sphere_va , circle_va , disk_va ;
2020-05-02 21:18:42 +00:00
static std : : array < std : : unique_ptr < GLfloat [ ] > , 3 > secondary_lva ;
2013-08-14 21:12:51 +00:00
static int r_polyc , r_tpolyc , r_bitmapc , r_ubitbltc ;
2008-10-28 17:04:35 +00:00
# define f2glf(x) (f2fl(x))
2007-01-09 01:23:49 +00:00
2007-02-19 15:30:13 +00:00
# define OGL_BINDTEXTURE(a) glBindTexture(GL_TEXTURE_2D, a);
2006-03-20 16:43:15 +00:00
2017-03-18 18:07:37 +00:00
/* I assume this ought to be >= MAX_BITMAP_FILES in piggy.h? */
2020-05-02 21:18:42 +00:00
static std : : array < ogl_texture , 20000 > ogl_texture_list ;
2013-08-14 21:12:51 +00:00
static int ogl_texture_list_cur ;
2006-03-20 16:43:15 +00:00
2021-03-09 20:59:20 +00:00
static GLboolean ogl_stereo_enabled = false ;
static GLint ogl_stereo_viewport [ 2 ] [ 4 ] ;
static GLfloat ogl_stereo_transform [ 2 ] [ 16 ] ;
2007-06-10 16:21:53 +00:00
/* some function prototypes */
# define GL_TEXTURE0_ARB 0x84C0
2021-01-17 22:23:23 +00:00
static int ogl_loadtexture ( const palette_array_t & , const uint8_t * data , int dxo , int dyo , ogl_texture & tex , int bm_flags , int data_format , opengl_texture_filter texfilt , bool texanis , bool edgepad ) __attribute_nonnull ( ) ;
2014-11-30 22:09:20 +00:00
static void ogl_freetexture ( ogl_texture & gltexture ) ;
2013-08-14 21:12:51 +00:00
2016-09-17 13:56:43 +00:00
static void ogl_loadbmtexture ( grs_bitmap & bm , bool edgepad )
2013-08-14 21:12:51 +00:00
{
2016-09-17 13:56:43 +00:00
ogl_loadbmtexture_f ( bm , CGameCfg . TexFilt , CGameCfg . TexAnisotropy , edgepad ) ;
2013-08-14 21:12:51 +00:00
}
2007-06-10 16:21:53 +00:00
2015-12-13 18:00:48 +00:00
}
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES
2011-01-06 11:43:55 +00:00
// Replacement for gluPerspective
2013-08-14 21:12:51 +00:00
static void perspective ( double fovy , double aspect , double zNear , double zFar )
2011-01-06 11:43:55 +00:00
{
double xmin , xmax , ymin , ymax ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
ymax = zNear * tan ( fovy * M_PI / 360.0 ) ;
ymin = - ymax ;
xmin = ymin * aspect ;
xmax = ymax * aspect ;
glFrustumf ( xmin , xmax , ymin , ymax , zNear , zFar ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST ) ;
glDepthMask ( GL_TRUE ) ;
}
# endif
2014-11-30 22:09:19 +00:00
static void ogl_init_texture_stats ( ogl_texture & t )
{
t . prio = 0.3 ; //default prio
t . numrend = 0 ;
2006-03-20 16:43:15 +00:00
}
2009-11-30 19:11:46 +00:00
2014-11-30 22:09:19 +00:00
void ogl_init_texture ( ogl_texture & t , int w , int h , int flags )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:19 +00:00
t . handle = 0 ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2007-06-10 16:21:53 +00:00
if ( flags & OGL_FLAG_NOCOLOR )
{
// use GL_INTENSITY instead of GL_RGB
if ( flags & OGL_FLAG_ALPHA )
{
2015-12-18 04:08:23 +00:00
if ( CGameArg . DbgGlIntensity4Ok )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:19 +00:00
t . internalformat = GL_INTENSITY4 ;
t . format = GL_LUMINANCE ;
2007-06-10 16:21:53 +00:00
}
2015-12-18 04:08:24 +00:00
else if ( CGameArg . DbgGlLuminance4Alpha4Ok )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:19 +00:00
t . internalformat = GL_LUMINANCE4_ALPHA4 ;
t . format = GL_LUMINANCE_ALPHA ;
2007-06-10 16:21:53 +00:00
}
2015-12-18 04:08:24 +00:00
else if ( CGameArg . DbgGlRGBA2Ok )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:19 +00:00
t . internalformat = GL_RGBA2 ;
t . format = GL_RGBA ;
2007-06-10 16:21:53 +00:00
}
else
{
2014-11-30 22:09:19 +00:00
t . internalformat = ogl_rgba_internalformat ;
t . format = GL_RGBA ;
2007-06-10 16:21:53 +00:00
}
}
else
{
// there are certainly smaller formats we could use here, but nothing needs it ATM.
2014-11-30 22:09:19 +00:00
t . internalformat = ogl_rgb_internalformat ;
t . format = GL_RGB ;
2007-06-10 16:21:53 +00:00
}
}
else
{
2011-01-06 11:43:55 +00:00
# endif
2007-06-10 16:21:53 +00:00
if ( flags & OGL_FLAG_ALPHA )
{
2014-11-30 22:09:19 +00:00
t . internalformat = ogl_rgba_internalformat ;
t . format = GL_RGBA ;
2007-06-10 16:21:53 +00:00
}
else
{
2014-11-30 22:09:19 +00:00
t . internalformat = ogl_rgb_internalformat ;
t . format = GL_RGB ;
2007-06-10 16:21:53 +00:00
}
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2007-06-10 16:21:53 +00:00
}
2011-01-06 11:43:55 +00:00
# endif
2014-11-30 22:09:19 +00:00
t . wrapstate = - 1 ;
t . lw = t . w = w ;
t . h = h ;
ogl_init_texture_stats ( t ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2014-11-30 22:09:19 +00:00
static void ogl_reset_texture ( ogl_texture & t )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:19 +00:00
ogl_init_texture ( t , 0 , 0 , 0 ) ;
2007-06-10 16:21:53 +00:00
}
2013-08-14 21:12:51 +00:00
static void ogl_reset_texture_stats_internal ( void ) {
2014-11-30 22:09:20 +00:00
range_for ( auto & i , ogl_texture_list )
if ( i . handle > 0 )
ogl_init_texture_stats ( i ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2006-03-20 16:43:15 +00:00
void ogl_init_texture_list_internal ( void ) {
ogl_texture_list_cur = 0 ;
2014-11-30 22:09:20 +00:00
range_for ( auto & i , ogl_texture_list )
ogl_reset_texture ( i ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2006-03-20 16:43:15 +00:00
void ogl_smash_texture_list_internal ( void ) {
2014-08-05 02:32:35 +00:00
sphere_va . reset ( ) ;
circle_va . reset ( ) ;
disk_va . reset ( ) ;
2014-08-05 02:32:55 +00:00
secondary_lva = { } ;
2014-11-30 22:09:20 +00:00
range_for ( auto & i , ogl_texture_list )
{
if ( i . handle > 0 ) {
glDeleteTextures ( 1 , & i . handle ) ;
i . handle = 0 ;
2006-03-20 16:43:15 +00:00
}
2014-11-30 22:09:20 +00:00
i . wrapstate = - 1 ;
2006-03-20 16:43:15 +00:00
}
}
ogl_texture * ogl_get_free_texture ( void ) {
2017-03-18 18:07:37 +00:00
for ( unsigned i = ogl_texture_list . size ( ) ; i - - ; )
{
2006-03-20 16:43:15 +00:00
if ( ogl_texture_list [ ogl_texture_list_cur ] . handle < = 0 & & ogl_texture_list [ ogl_texture_list_cur ] . w = = 0 )
return & ogl_texture_list [ ogl_texture_list_cur ] ;
2017-03-18 18:07:37 +00:00
if ( + + ogl_texture_list_cur > = ogl_texture_list . size ( ) )
2006-03-20 16:43:15 +00:00
ogl_texture_list_cur = 0 ;
}
Error ( " OGL: texture list full! \n " ) ;
}
2007-06-10 16:21:53 +00:00
2013-10-27 22:00:14 +00:00
static void ogl_texture_stats ( void )
2008-10-28 17:04:35 +00:00
{
2007-06-10 16:21:53 +00:00
int used = 0 , usedother = 0 , usedidx = 0 , usedrgb = 0 , usedrgba = 0 ;
2014-11-30 22:09:20 +00:00
int databytes = 0 , truebytes = 0 , datatexel = 0 , truetexel = 0 ;
2006-03-20 16:43:15 +00:00
int prio0 = 0 , prio1 = 0 , prio2 = 0 , prio3 = 0 , prioh = 0 ;
2008-10-28 17:04:35 +00:00
GLint idx , r , g , b , a , dbl , depth ;
int res , colorsize , depthsize ;
2014-11-30 22:09:20 +00:00
range_for ( auto & i , ogl_texture_list )
{
if ( i . handle > 0 ) {
2006-03-20 16:43:15 +00:00
used + + ;
2014-11-30 22:09:20 +00:00
datatexel + = i . w * i . h ;
truetexel + = i . tw * i . th ;
databytes + = i . bytesu ;
truebytes + = i . bytes ;
if ( i . prio < 0.299 ) prio0 + + ;
else if ( i . prio < 0.399 ) prio1 + + ;
else if ( i . prio < 0.499 ) prio2 + + ;
else if ( i . prio < 0.599 ) prio3 + + ;
2006-03-20 16:43:15 +00:00
else prioh + + ;
2014-11-30 22:09:20 +00:00
if ( i . format = = GL_RGBA )
2007-06-10 16:21:53 +00:00
usedrgba + + ;
2014-11-30 22:09:20 +00:00
else if ( i . format = = GL_RGB )
2007-06-10 16:21:53 +00:00
usedrgb + + ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2014-11-30 22:09:20 +00:00
else if ( i . format = = GL_COLOR_INDEX )
2007-06-10 16:21:53 +00:00
usedidx + + ;
2011-01-06 11:43:55 +00:00
# endif
2007-06-10 16:21:53 +00:00
else
usedother + + ;
2006-03-20 16:43:15 +00:00
}
}
2007-06-10 16:21:53 +00:00
2008-10-28 17:04:35 +00:00
res = SWIDTH * SHEIGHT ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2008-10-28 17:04:35 +00:00
glGetIntegerv ( GL_INDEX_BITS , & idx ) ;
2015-04-04 21:04:24 +00:00
# else
idx = 16 ;
2011-01-06 11:43:55 +00:00
# endif
2008-10-28 17:04:35 +00:00
glGetIntegerv ( GL_RED_BITS , & r ) ;
glGetIntegerv ( GL_GREEN_BITS , & g ) ;
glGetIntegerv ( GL_BLUE_BITS , & b ) ;
glGetIntegerv ( GL_ALPHA_BITS , & a ) ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2008-10-28 17:04:35 +00:00
glGetIntegerv ( GL_DOUBLEBUFFER , & dbl ) ;
2015-04-04 21:04:24 +00:00
# else
dbl = 1 ;
2011-01-06 11:43:55 +00:00
# endif
2008-10-28 17:04:35 +00:00
dbl + = 1 ;
glGetIntegerv ( GL_DEPTH_BITS , & depth ) ;
2017-11-05 20:49:08 +00:00
gr_set_default_canvas ( ) ;
2017-03-10 01:22:26 +00:00
auto & canvas = * grd_curcanv ;
2018-05-19 23:21:42 +00:00
const auto & game_font = * GAME_FONT ;
2017-03-10 01:22:26 +00:00
gr_set_fontcolor ( canvas , BM_XRGB ( 255 , 255 , 255 ) , - 1 ) ;
2008-10-28 17:04:35 +00:00
colorsize = ( idx * res * dbl ) / 8 ;
depthsize = res * depth / 8 ;
2015-06-13 22:42:20 +00:00
const auto & & fspacx2 = FSPACX ( 2 ) ;
const auto & & fspacy1 = FSPACY ( 1 ) ;
2018-05-19 23:21:42 +00:00
const auto & & line_spacing = LINE_SPACING ( game_font , game_font ) ;
gr_printf ( canvas , game_font , fspacx2 , fspacy1 , " %i flat %i tex %i bitmaps " , r_polyc , r_tpolyc , r_bitmapc ) ;
gr_printf ( canvas , game_font , fspacx2 , fspacy1 + line_spacing , " %i(%i,%i,%i,%i) %iK(%iK wasted) (%i postcachedtex) " , used , usedrgba , usedrgb , usedidx , usedother , truebytes / 1024 , ( truebytes - databytes ) / 1024 , r_texcount - r_cachedtexcount ) ;
gr_printf ( canvas , game_font , fspacx2 , fspacy1 + ( line_spacing * 2 ) , " %ibpp(r%i,g%i,b%i,a%i)x%i=%iK depth%i=%iK " , idx , r , g , b , a , dbl , colorsize / 1024 , depth , depthsize / 1024 ) ;
gr_printf ( canvas , game_font , fspacx2 , fspacy1 + ( line_spacing * 3 ) , " total=%iK " , ( colorsize + depthsize + truebytes ) / 1024 ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2016-09-17 13:56:43 +00:00
static void ogl_bindbmtex ( grs_bitmap & bm , bool edgepad ) {
2014-11-13 03:43:12 +00:00
if ( bm . gltexture = = NULL | | bm . gltexture - > handle < = 0 )
2016-09-17 13:56:43 +00:00
ogl_loadbmtexture ( bm , edgepad ) ;
2014-11-13 03:43:12 +00:00
OGL_BINDTEXTURE ( bm . gltexture - > handle ) ;
bm . gltexture - > numrend + + ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2006-03-20 16:43:15 +00:00
//gltexture MUST be bound first
2017-07-26 03:15:59 +00:00
static void ogl_texwrap ( ogl_texture * const gltexture , const int state )
2007-06-10 16:21:53 +00:00
{
if ( gltexture - > wrapstate ! = state | | gltexture - > numrend < 1 )
{
2017-07-26 03:15:59 +00:00
gltexture - > wrapstate = state ;
2006-03-20 16:43:15 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , state ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , state ) ;
}
}
//crude texture precaching
//handles: powerups, walls, weapons, polymodels, etc.
//it is done with the horrid do_special_effects kludge so that sides that have to be texmerged and have animated textures will be correctly cached.
//similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level
//TODO: doors
2017-07-26 03:15:59 +00:00
void ogl_cache_polymodel_textures ( const unsigned model_num )
2007-06-10 16:21:53 +00:00
{
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2017-07-26 03:15:59 +00:00
if ( model_num > = Polygon_models . size ( ) )
2007-06-10 16:21:53 +00:00
return ;
2017-07-26 03:15:59 +00:00
const auto & po = Polygon_models [ model_num ] ;
unsigned i = po . first_texture ;
const unsigned last_texture = i + po . n_textures ;
for ( ; i ! = last_texture ; + + i )
{
2020-04-04 19:30:22 +00:00
auto & objbitmap = ObjBitmaps [ ObjBitmapPtrs [ i ] ] ;
PIGGY_PAGE_IN ( objbitmap ) ;
ogl_loadbmtexture ( GameBitmaps [ objbitmap . index ] , 1 ) ;
2006-03-20 16:43:15 +00:00
}
}
2009-11-30 19:11:46 +00:00
2017-07-26 03:15:59 +00:00
static void ogl_cache_vclip_textures ( const vclip & vc )
{
range_for ( auto & i , partial_const_range ( vc . frames , vc . num_frames ) )
2016-01-17 05:19:10 +00:00
{
PIGGY_PAGE_IN ( i ) ;
2016-09-17 13:56:43 +00:00
ogl_loadbmtexture ( GameBitmaps [ i . index ] , 0 ) ;
2006-03-20 16:43:15 +00:00
}
}
2007-06-10 16:21:53 +00:00
2018-10-21 00:24:07 +00:00
static void ogl_cache_vclipn_textures ( const d_vclip_array & Vclip , const unsigned i )
2007-06-10 16:21:53 +00:00
{
2016-01-17 05:19:10 +00:00
if ( i < Vclip . size ( ) )
2017-07-26 03:15:59 +00:00
ogl_cache_vclip_textures ( Vclip [ i ] ) ;
2007-06-10 16:21:53 +00:00
}
2018-10-21 00:24:07 +00:00
static void ogl_cache_weapon_textures ( const d_vclip_array & Vclip , const weapon_info_array & Weapon_info , const unsigned weapon_type )
2007-06-10 16:21:53 +00:00
{
2017-07-26 03:15:59 +00:00
if ( weapon_type > = Weapon_info . size ( ) )
2007-06-10 16:21:53 +00:00
return ;
2017-07-26 03:15:59 +00:00
const auto & w = Weapon_info [ weapon_type ] ;
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , w . flash_vclip ) ;
ogl_cache_vclipn_textures ( Vclip , w . robot_hit_vclip ) ;
ogl_cache_vclipn_textures ( Vclip , w . wall_hit_vclip ) ;
2020-08-24 01:31:28 +00:00
if ( w . render = = WEAPON_RENDER_VCLIP )
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , w . weapon_vclip ) ;
2020-08-24 01:31:28 +00:00
else if ( w . render = = WEAPON_RENDER_POLYMODEL )
2007-06-10 16:21:53 +00:00
{
2017-07-26 03:15:59 +00:00
ogl_cache_polymodel_textures ( w . model_num ) ;
ogl_cache_polymodel_textures ( w . model_num_inner ) ;
2007-06-10 16:21:53 +00:00
}
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-13 18:00:48 +00:00
2007-06-10 16:21:53 +00:00
void ogl_cache_level_textures ( void )
{
2019-03-03 00:31:09 +00:00
auto & Effects = LevelUniqueEffectsClipState . Effects ;
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptridx = Objects . vcptridx ;
2006-03-20 16:43:15 +00:00
int max_efx = 0 , ef ;
ogl_reset_texture_stats_internal ( ) ; //loading a new lev should reset textures
2016-02-12 04:02:28 +00:00
range_for ( auto & ec , partial_const_range ( Effects , Num_effects ) )
2014-01-18 18:02:02 +00:00
{
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , ec . dest_vclip ) ;
2020-10-07 03:59:14 +00:00
if ( ec . changing_wall_texture = = - 1 & & ec . changing_object_texture = = object_bitmap_index : : None )
2006-03-20 16:43:15 +00:00
continue ;
2014-01-19 22:58:24 +00:00
if ( ec . vc . num_frames > max_efx )
max_efx = ec . vc . num_frames ;
2006-03-20 16:43:15 +00:00
}
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " max_efx:%i " , max_efx ) ) ;
2006-03-20 16:43:15 +00:00
for ( ef = 0 ; ef < max_efx ; ef + + ) {
2014-01-18 18:02:02 +00:00
range_for ( eclip & ec , partial_range ( Effects , Num_effects ) )
{
2020-10-07 03:59:14 +00:00
if ( ec . changing_wall_texture = = - 1 & & ec . changing_object_texture = = object_bitmap_index : : None )
2006-03-20 16:43:15 +00:00
continue ;
2014-01-19 22:58:24 +00:00
ec . time_left = - 1 ;
2006-03-20 16:43:15 +00:00
}
do_special_effects ( ) ;
2018-12-13 02:31:38 +00:00
range_for ( const unique_segment & seg , vcsegptr )
2016-10-15 00:53:17 +00:00
{
2018-12-13 02:31:38 +00:00
range_for ( auto & side , seg . sides )
2016-10-15 00:53:17 +00:00
{
const auto tmap1 = side . tmap_num ;
const auto tmap2 = side . tmap_num2 ;
2020-09-11 03:08:02 +00:00
const auto tmap1idx = get_texture_index ( tmap1 ) ;
if ( tmap1idx > = NumTextures ) {
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " ogl_cache_level_textures %p %p %i %i " , seg . get_unchecked_pointer ( ) , & side , tmap1 , NumTextures ) ) ;
2006-03-20 16:43:15 +00:00
// tmap1=0;
continue ;
}
2020-09-11 03:08:02 +00:00
auto & texture1 = Textures [ tmap1idx ] ;
PIGGY_PAGE_IN ( texture1 ) ;
grs_bitmap * bm = & GameBitmaps [ texture1 . index ] ;
2020-08-24 01:31:28 +00:00
if ( tmap2 ! = texture2_value : : None )
{
const auto texture2 = Textures [ get_texture_index ( tmap2 ) ] ;
PIGGY_PAGE_IN ( texture2 ) ;
auto & bm2 = GameBitmaps [ texture2 . index ] ;
2017-01-15 00:03:13 +00:00
if ( CGameArg . DbgUseOldTextureMerge | | bm2 . get_flag_mask ( BM_FLAG_SUPER_TRANSPARENT ) )
2014-11-30 22:09:19 +00:00
bm = & texmerge_get_cached_bitmap ( tmap1 , tmap2 ) ;
2006-03-20 16:43:15 +00:00
else {
2016-09-17 13:56:43 +00:00
ogl_loadbmtexture ( bm2 , 1 ) ;
2006-03-20 16:43:15 +00:00
}
}
2016-09-17 16:26:59 +00:00
ogl_loadbmtexture ( * bm , 0 ) ;
2006-03-20 16:43:15 +00:00
}
}
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " finished ef:%i " , ef ) ) ;
2006-03-20 16:43:15 +00:00
}
reset_special_effects ( ) ;
init_special_effects ( ) ;
{
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2007-06-10 16:21:53 +00:00
// always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
2018-10-21 00:24:07 +00:00
ogl_cache_weapon_textures ( Vclip , Weapon_info , Primary_weapon_to_weapon_info [ primary_weapon_index_t : : LASER_INDEX ] ) ;
ogl_cache_weapon_textures ( Vclip , Weapon_info , Secondary_weapon_to_weapon_info [ CONCUSSION_INDEX ] ) ;
ogl_cache_weapon_textures ( Vclip , Weapon_info , weapon_id_type : : FLARE_ID ) ;
ogl_cache_vclipn_textures ( Vclip , VCLIP_PLAYER_APPEARANCE ) ;
ogl_cache_vclipn_textures ( Vclip , VCLIP_POWERUP_DISAPPEARANCE ) ;
2007-06-10 16:21:53 +00:00
ogl_cache_polymodel_textures ( Player_ship - > model_num ) ;
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , Player_ship - > expl_vclip_num ) ;
2007-06-10 16:21:53 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-01-28 03:42:52 +00:00
if ( objp - > type = = OBJ_POWERUP & & objp - > render_type = = RT_POWERUP )
{
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , objp - > rtype . vclip_info . vclip_num ) ;
2016-01-17 05:19:10 +00:00
const auto id = get_powerup_id ( objp ) ;
primary_weapon_index_t p ;
secondary_weapon_index_t s ;
int w ;
if (
(
(
( id = = POW_VULCAN_WEAPON & & ( p = primary_weapon_index_t : : VULCAN_INDEX , true ) ) | |
( id = = POW_SPREADFIRE_WEAPON & & ( p = primary_weapon_index_t : : SPREADFIRE_INDEX , true ) ) | |
( id = = POW_PLASMA_WEAPON & & ( p = primary_weapon_index_t : : PLASMA_INDEX , true ) ) | |
( id = = POW_FUSION_WEAPON & & ( p = primary_weapon_index_t : : FUSION_INDEX , true ) )
) & & ( w = Primary_weapon_to_weapon_info [ p ] , true )
) | |
(
(
( id = = POW_PROXIMITY_WEAPON & & ( s = secondary_weapon_index_t : : PROXIMITY_INDEX , true ) ) | |
( ( id = = POW_HOMING_AMMO_1 | | id = = POW_HOMING_AMMO_4 ) & & ( s = secondary_weapon_index_t : : HOMING_INDEX , true ) ) | |
( id = = POW_SMARTBOMB_WEAPON & & ( s = secondary_weapon_index_t : : SMART_INDEX , true ) ) | |
( id = = POW_MEGA_WEAPON & & ( s = secondary_weapon_index_t : : MEGA_INDEX , true ) )
) & & ( w = Secondary_weapon_to_weapon_info [ s ] , true )
)
)
{
2018-10-21 00:24:07 +00:00
ogl_cache_weapon_textures ( Vclip , Weapon_info , w ) ;
2006-03-20 16:43:15 +00:00
}
}
2015-01-28 03:42:52 +00:00
else if ( objp - > type ! = OBJ_NONE & & objp - > render_type = = RT_POLYOBJ )
{
2015-06-13 22:42:18 +00:00
if ( objp - > type = = OBJ_ROBOT )
2007-06-10 16:21:53 +00:00
{
2016-01-17 05:19:10 +00:00
auto & ri = Robot_info [ get_robot_id ( objp ) ] ;
2018-10-21 00:24:07 +00:00
ogl_cache_vclipn_textures ( Vclip , ri . exp1_vclip_num ) ;
ogl_cache_vclipn_textures ( Vclip , ri . exp2_vclip_num ) ;
ogl_cache_weapon_textures ( Vclip , Weapon_info , ri . weapon_type ) ;
2007-06-10 16:21:53 +00:00
}
2015-06-13 22:42:18 +00:00
if ( objp - > rtype . pobj_info . tmap_override ! = - 1 )
2016-10-23 20:33:14 +00:00
{
auto & t = Textures [ objp - > rtype . pobj_info . tmap_override ] ;
PIGGY_PAGE_IN ( t ) ;
ogl_loadbmtexture ( GameBitmaps [ t . index ] , 1 ) ;
}
2007-06-10 16:21:53 +00:00
else
2015-06-13 22:42:18 +00:00
ogl_cache_polymodel_textures ( objp - > rtype . pobj_info . model_num ) ;
2006-03-20 16:43:15 +00:00
}
}
}
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " finished caching " ) ) ;
2007-06-10 16:21:53 +00:00
r_cachedtexcount = r_texcount ;
2006-03-20 16:43:15 +00:00
}
2015-12-13 18:00:48 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:24 +00:00
2017-02-11 21:42:33 +00:00
void g3_draw_line ( grs_canvas & canvas , const g3s_point & p0 , const g3s_point & p1 , const uint8_t c )
2006-03-20 16:43:15 +00:00
{
2011-01-06 11:43:55 +00:00
GLfloat color_r , color_g , color_b ;
GLfloat color_array [ ] = { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 } ;
2016-01-09 16:38:10 +00:00
ogl_client_states < int , GL_VERTEX_ARRAY , GL_COLOR_ARRAY > cs ;
2006-03-20 16:43:15 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2020-07-02 20:07:01 +00:00
glDisable ( GL_CULL_FACE ) ;
2011-01-06 11:43:55 +00:00
color_r = PAL2Tr ( c ) ;
color_g = PAL2Tg ( c ) ;
color_b = PAL2Tb ( c ) ;
color_array [ 0 ] = color_array [ 4 ] = color_r ;
color_array [ 1 ] = color_array [ 5 ] = color_g ;
color_array [ 2 ] = color_array [ 6 ] = color_b ;
color_array [ 3 ] = color_array [ 7 ] = 1.0 ;
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 6 > vertices = { {
2017-07-08 18:17:49 +00:00
f2glf ( p0 . p3_vec . x ) , f2glf ( p0 . p3_vec . y ) , - f2glf ( p0 . p3_vec . z ) ,
f2glf ( p1 . p3_vec . x ) , f2glf ( p1 . p3_vec . y ) , - f2glf ( p1 . p3_vec . z )
} } ;
glVertexPointer ( 3 , GL_FLOAT , 0 , vertices . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , color_array ) ;
glDrawArrays ( GL_LINES , 0 , 2 ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2017-07-08 18:17:49 +00:00
static void ogl_drawcircle ( const unsigned nsides , const unsigned type , GLfloat * const vertices )
2011-01-06 11:43:55 +00:00
{
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2017-07-08 18:17:49 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , vertices ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( type , 0 , nsides ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2017-07-08 18:17:49 +00:00
static std : : unique_ptr < GLfloat [ ] > circle_array_init ( const unsigned nsides )
2011-01-06 11:43:55 +00:00
{
2020-05-02 21:18:42 +00:00
auto vertices = std : : make_unique < GLfloat [ ] > ( nsides * 2 ) ;
2017-07-08 18:17:49 +00:00
for ( unsigned i = 0 ; i < nsides ; i + + )
{
const float ang = 2.0 * M_PI * i / nsides ;
2017-07-08 18:17:49 +00:00
vertices [ i * 2 ] = cosf ( ang ) ;
2017-07-08 18:17:49 +00:00
vertices [ i * 2 + 1 ] = sinf ( ang ) ;
2006-03-20 16:43:15 +00:00
}
2017-07-08 18:17:49 +00:00
return vertices ;
2006-03-20 16:43:15 +00:00
}
2013-08-14 21:12:51 +00:00
2017-07-08 18:17:49 +00:00
static std : : unique_ptr < GLfloat [ ] > circle_array_init_2 ( const unsigned nsides , const float xsc , const float xo , const float ysc , const float yo )
2011-01-06 11:43:55 +00:00
{
2020-05-02 21:18:42 +00:00
auto vertices = std : : make_unique < GLfloat [ ] > ( nsides * 2 ) ;
2017-07-08 18:17:49 +00:00
for ( unsigned i = 0 ; i < nsides ; i + + )
{
const float ang = 2.0 * M_PI * i / nsides ;
2017-07-08 18:17:49 +00:00
vertices [ i * 2 ] = cosf ( ang ) * xsc + xo ;
vertices [ i * 2 + 1 ] = sinf ( ang ) * ysc + yo ;
2011-01-06 11:43:55 +00:00
}
2017-07-08 18:17:49 +00:00
return vertices ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2017-07-08 18:17:49 +00:00
}
2011-01-10 15:12:00 +00:00
void ogl_draw_vertex_reticle ( int cross , int primary , int secondary , int color , int alpha , int size_offs )
2008-04-19 19:11:32 +00:00
{
2015-04-02 02:36:56 +00:00
int size = 270 + ( size_offs * 20 ) ;
2016-06-05 01:04:26 +00:00
float scale = ( static_cast < float > ( SWIDTH ) / SHEIGHT ) ;
2020-05-02 21:18:42 +00:00
const std : : array < float , 4 > ret_rgba { {
2015-04-02 02:36:55 +00:00
static_cast < float > ( PAL2Tr ( color ) ) ,
static_cast < float > ( PAL2Tg ( color ) ) ,
static_cast < float > ( PAL2Tb ( color ) ) ,
2016-06-05 01:04:26 +00:00
static_cast < float > ( 1.0 - ( static_cast < float > ( alpha ) / ( static_cast < float > ( GR_FADE_LEVELS ) ) ) )
2015-04-02 02:36:55 +00:00
} } , ret_dark_rgba { {
ret_rgba [ 0 ] / 2 ,
ret_rgba [ 1 ] / 2 ,
ret_rgba [ 2 ] / 2 ,
ret_rgba [ 3 ] / 2
} } ;
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 16 * 4 > dark_lca , bright_lca ;
2015-04-02 02:36:56 +00:00
for ( uint_fast32_t i = 0 ; i ! = dark_lca . size ( ) ; i + = 4 )
2011-01-10 15:12:00 +00:00
{
bright_lca [ i ] = ret_rgba [ 0 ] ;
dark_lca [ i ] = ret_dark_rgba [ 0 ] ;
bright_lca [ i + 1 ] = ret_rgba [ 1 ] ;
dark_lca [ i + 1 ] = ret_dark_rgba [ 1 ] ;
bright_lca [ i + 2 ] = ret_rgba [ 2 ] ;
dark_lca [ i + 2 ] = ret_dark_rgba [ 2 ] ;
bright_lca [ i + 3 ] = ret_rgba [ 3 ] ;
dark_lca [ i + 3 ] = ret_dark_rgba [ 3 ] ;
}
2006-03-20 16:43:15 +00:00
glPushMatrix ( ) ;
2016-06-05 01:04:26 +00:00
glTranslatef ( ( grd_curcanv - > cv_bitmap . bm_w / 2 + grd_curcanv - > cv_bitmap . bm_x ) / static_cast < float > ( last_width ) , 1.0 - ( grd_curcanv - > cv_bitmap . bm_h / 2 + grd_curcanv - > cv_bitmap . bm_y ) / static_cast < float > ( last_height ) , 0 ) ;
2008-11-09 14:31:30 +00:00
2016-04-05 01:10:18 +00:00
{
float gl1 , gl2 , gl3 ;
2008-11-09 14:31:30 +00:00
if ( scale > = 1 )
{
size / = scale ;
2016-04-05 01:10:18 +00:00
gl2 = f2glf ( size * scale ) ;
gl1 = f2glf ( size ) ;
gl3 = gl1 ;
2008-11-09 14:31:30 +00:00
}
else
{
size * = scale ;
2016-04-05 01:10:18 +00:00
gl1 = f2glf ( size / scale ) ;
gl2 = f2glf ( size ) ;
gl3 = gl2 ;
}
glScalef ( gl1 , gl2 , gl3 ) ;
2008-11-09 14:31:30 +00:00
}
glLineWidth ( linedotscale * 2 ) ;
2006-03-20 16:43:15 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2006-07-11 16:13:47 +00:00
glDisable ( GL_CULL_FACE ) ;
2011-01-06 11:43:55 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
//cross
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 8 * 4 > cross_lca ;
2016-08-29 15:07:30 +00:00
GLfloat * cross_lca_ptr ;
2016-04-05 01:10:18 +00:00
if ( cross )
{
2015-04-02 02:36:55 +00:00
for ( uint_fast32_t i = 0 ; i ! = cross_lca . size ( ) ; i + = 8 )
{
cross_lca [ i ] = ret_dark_rgba [ 0 ] ;
cross_lca [ i + 1 ] = ret_dark_rgba [ 1 ] ;
cross_lca [ i + 2 ] = ret_dark_rgba [ 2 ] ;
cross_lca [ i + 3 ] = ret_dark_rgba [ 3 ] ;
cross_lca [ i + 4 ] = ret_rgba [ 0 ] ;
cross_lca [ i + 5 ] = ret_rgba [ 1 ] ;
cross_lca [ i + 6 ] = ret_rgba [ 2 ] ;
cross_lca [ i + 7 ] = ret_rgba [ 3 ] ;
}
2016-04-05 01:10:18 +00:00
cross_lca_ptr = cross_lca . data ( ) ;
2015-04-02 02:36:55 +00:00
}
2008-04-19 19:11:32 +00:00
else
2016-08-29 15:07:30 +00:00
{
2016-04-05 01:10:18 +00:00
cross_lca_ptr = dark_lca . data ( ) ;
}
2016-08-29 15:07:30 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , cross_lca_ptr ) ;
2020-05-02 21:18:42 +00:00
static const std : : array < GLfloat , 8 * 2 > cross_lva { {
2015-04-02 02:36:55 +00:00
- 4.0 , 2.0 , - 2.0 , 0 , - 3.0 , - 4.0 , - 2.0 , - 3.0 , 4.0 , 2.0 , 2.0 , 0 , 3.0 , - 4.0 , 2.0 , - 3.0 ,
} } ;
glVertexPointer ( 2 , GL_FLOAT , 0 , cross_lva . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_LINES , 0 , 8 ) ;
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 4 * 4 > primary_lca0 ;
2016-04-05 01:10:18 +00:00
GLfloat * lca0_data ;
2011-01-06 11:43:55 +00:00
//left primary bar
if ( primary = = 0 )
2016-04-05 01:10:18 +00:00
lca0_data = dark_lca . data ( ) ;
2011-01-06 11:43:55 +00:00
else
2015-04-02 02:36:55 +00:00
{
primary_lca0 [ 0 ] = primary_lca0 [ 4 ] = ret_rgba [ 0 ] ;
primary_lca0 [ 1 ] = primary_lca0 [ 5 ] = ret_rgba [ 1 ] ;
primary_lca0 [ 2 ] = primary_lca0 [ 6 ] = ret_rgba [ 2 ] ;
primary_lca0 [ 3 ] = primary_lca0 [ 7 ] = ret_rgba [ 3 ] ;
primary_lca0 [ 8 ] = primary_lca0 [ 12 ] = ret_dark_rgba [ 0 ] ;
primary_lca0 [ 9 ] = primary_lca0 [ 13 ] = ret_dark_rgba [ 1 ] ;
primary_lca0 [ 10 ] = primary_lca0 [ 14 ] = ret_dark_rgba [ 2 ] ;
primary_lca0 [ 11 ] = primary_lca0 [ 15 ] = ret_dark_rgba [ 3 ] ;
2016-04-05 01:10:18 +00:00
lca0_data = primary_lca0 . data ( ) ;
2015-04-02 02:36:55 +00:00
}
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , lca0_data ) ;
2020-05-02 21:18:42 +00:00
static const std : : array < GLfloat , 4 * 2 > primary_lva0 { {
2015-04-02 02:36:55 +00:00
- 5.5 , - 5.0 , - 6.5 , - 7.5 , - 10.0 , - 7.0 , - 10.0 , - 8.7
} } ;
2020-05-02 21:18:42 +00:00
static const std : : array < GLfloat , 4 * 2 > primary_lva1 { {
2015-04-02 02:36:55 +00:00
- 10.0 , - 7.0 , - 10.0 , - 8.7 , - 15.0 , - 8.5 , - 15.0 , - 9.5
} } ;
2020-05-02 21:18:42 +00:00
static const std : : array < GLfloat , 4 * 2 > primary_lva2 { {
2015-04-02 02:36:55 +00:00
5.5 , - 5.0 , 6.5 , - 7.5 , 10.0 , - 7.0 , 10.0 , - 8.7
} } ;
2020-05-02 21:18:42 +00:00
static const std : : array < GLfloat , 4 * 2 > primary_lva3 { {
2015-04-02 02:36:55 +00:00
10.0 , - 7.0 , 10.0 , - 8.7 , 15.0 , - 8.5 , 15.0 , - 9.5
} } ;
glVertexPointer ( 2 , GL_FLOAT , 0 , primary_lva0 . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
2015-04-02 02:36:55 +00:00
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 4 * 4 > primary_lca1 ;
2016-04-05 01:10:18 +00:00
GLfloat * lca1_data ;
2011-01-06 11:43:55 +00:00
if ( primary ! = 2 )
2016-04-05 01:10:18 +00:00
lca1_data = dark_lca . data ( ) ;
2011-01-06 11:43:55 +00:00
else
2015-04-02 02:36:55 +00:00
{
primary_lca1 [ 8 ] = primary_lca1 [ 12 ] = ret_rgba [ 0 ] ;
primary_lca1 [ 9 ] = primary_lca1 [ 13 ] = ret_rgba [ 1 ] ;
primary_lca1 [ 10 ] = primary_lca1 [ 14 ] = ret_rgba [ 2 ] ;
primary_lca1 [ 11 ] = primary_lca1 [ 15 ] = ret_rgba [ 3 ] ;
primary_lca1 [ 0 ] = primary_lca1 [ 4 ] = ret_dark_rgba [ 0 ] ;
primary_lca1 [ 1 ] = primary_lca1 [ 5 ] = ret_dark_rgba [ 1 ] ;
primary_lca1 [ 2 ] = primary_lca1 [ 6 ] = ret_dark_rgba [ 2 ] ;
primary_lca1 [ 3 ] = primary_lca1 [ 7 ] = ret_dark_rgba [ 3 ] ;
2016-04-05 01:10:18 +00:00
lca1_data = primary_lca1 . data ( ) ;
2015-04-02 02:36:55 +00:00
}
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , lca1_data ) ;
2015-04-02 02:36:55 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , primary_lva1 . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
//right primary bar
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , lca0_data ) ;
2015-04-02 02:36:55 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , primary_lva2 . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , lca1_data ) ;
2015-04-02 02:36:55 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , primary_lva3 . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
2016-04-05 01:10:18 +00:00
GLfloat * secondary_lva_ptr ;
2011-01-06 11:43:55 +00:00
if ( secondary < = 2 ) {
//left secondary
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , ( secondary ! = 1 ? dark_lca : bright_lca ) . data ( ) ) ;
2011-01-06 11:43:55 +00:00
if ( ! secondary_lva [ 0 ] )
secondary_lva [ 0 ] = circle_array_init_2 ( 16 , 2.0 , - 10.0 , 2.0 , - 2.0 ) ;
2014-08-05 02:32:55 +00:00
ogl_drawcircle ( 16 , GL_LINE_LOOP , secondary_lva [ 0 ] . get ( ) ) ;
2011-01-06 11:43:55 +00:00
//right secondary
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , ( secondary ! = 2 ? dark_lca : bright_lca ) . data ( ) ) ;
2011-01-06 11:43:55 +00:00
if ( ! secondary_lva [ 1 ] )
secondary_lva [ 1 ] = circle_array_init_2 ( 16 , 2.0 , 10.0 , 2.0 , - 2.0 ) ;
2016-04-05 01:10:18 +00:00
secondary_lva_ptr = secondary_lva [ 1 ] . get ( ) ;
2008-04-19 19:11:32 +00:00
}
2011-01-06 11:43:55 +00:00
else {
//bottom/middle secondary
2016-04-05 01:10:18 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , ( secondary ! = 4 ? dark_lca : bright_lca ) . data ( ) ) ;
2011-01-06 11:43:55 +00:00
if ( ! secondary_lva [ 2 ] )
secondary_lva [ 2 ] = circle_array_init_2 ( 16 , 2.0 , 0.0 , 2.0 , - 8.0 ) ;
2016-04-05 01:10:18 +00:00
secondary_lva_ptr = secondary_lva [ 2 ] . get ( ) ;
2008-04-19 19:11:32 +00:00
}
2016-04-05 01:10:18 +00:00
ogl_drawcircle ( 16 , GL_LINE_LOOP , secondary_lva_ptr ) ;
2011-01-06 11:43:55 +00:00
//glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState ( GL_COLOR_ARRAY ) ;
2006-03-20 16:43:15 +00:00
glPopMatrix ( ) ;
2011-02-02 01:12:09 +00:00
glLineWidth ( linedotscale ) ;
2006-03-20 16:43:15 +00:00
}
2008-02-27 22:05:58 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:24 +00:00
2011-01-06 11:43:55 +00:00
/*
* Stars on heaven in exit sequence , automap objects
*/
2017-08-16 01:54:26 +00:00
void g3_draw_sphere ( grs_canvas & canvas , cg3s_point & pnt , fix rad , const uint8_t c )
2014-11-13 03:22:49 +00:00
{
2016-02-12 04:02:28 +00:00
int i ;
2017-03-11 19:56:24 +00:00
const float scale = ( static_cast < float > ( canvas . cv_bitmap . bm_w ) / canvas . cv_bitmap . bm_h ) ;
2020-05-02 21:18:42 +00:00
std : : array < GLfloat , 20 * 4 > color_array ;
2011-01-06 11:43:55 +00:00
for ( i = 0 ; i < 20 * 4 ; i + = 4 )
{
color_array [ i ] = CPAL2Tr ( c ) ;
color_array [ i + 1 ] = CPAL2Tg ( c ) ;
color_array [ i + 2 ] = CPAL2Tb ( c ) ;
color_array [ i + 3 ] = 1.0 ;
}
2006-03-20 16:43:15 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2007-06-10 16:21:53 +00:00
glDisable ( GL_CULL_FACE ) ;
2006-03-20 16:43:15 +00:00
glPushMatrix ( ) ;
2014-11-13 03:22:49 +00:00
glTranslatef ( f2glf ( pnt . p3_vec . x ) , f2glf ( pnt . p3_vec . y ) , - f2glf ( pnt . p3_vec . z ) ) ;
2016-09-03 17:30:17 +00:00
GLfloat gl1 , gl2 ;
2008-11-09 14:31:30 +00:00
if ( scale > = 1 )
{
rad / = scale ;
2016-09-03 17:30:17 +00:00
gl1 = f2glf ( rad ) ;
gl2 = f2glf ( rad * scale ) ;
2008-11-09 14:31:30 +00:00
}
else
{
rad * = scale ;
2016-09-03 17:30:17 +00:00
gl1 = f2glf ( rad / scale ) ;
gl2 = f2glf ( rad ) ;
2008-11-09 14:31:30 +00:00
}
2016-09-03 17:30:17 +00:00
glScalef ( gl1 , gl2 , f2glf ( rad ) ) ;
2011-01-06 11:43:55 +00:00
if ( ! sphere_va )
sphere_va = circle_array_init ( 20 ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
2017-07-08 18:17:49 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . data ( ) ) ;
2014-08-05 02:32:35 +00:00
ogl_drawcircle ( 20 , GL_TRIANGLE_FAN , sphere_va . get ( ) ) ;
2011-01-06 11:43:55 +00:00
glDisableClientState ( GL_COLOR_ARRAY ) ;
2006-03-20 16:43:15 +00:00
glPopMatrix ( ) ;
}
2007-06-10 16:21:53 +00:00
2016-12-29 03:27:13 +00:00
int gr_ucircle ( grs_canvas & canvas , const fix xc1 , const fix yc1 , const fix r1 , const uint8_t c )
2007-06-10 16:21:53 +00:00
{
2016-02-12 04:02:28 +00:00
int nsides ;
2006-03-20 16:43:15 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2016-12-29 03:27:13 +00:00
glColor4f ( CPAL2Tr ( c ) , CPAL2Tg ( c ) , CPAL2Tb ( c ) , ( canvas . cv_fade_level > = GR_FADE_OFF ) ? 1.0 : 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ) ;
2006-03-20 16:43:15 +00:00
glPushMatrix ( ) ;
glTranslatef (
2016-12-29 03:27:13 +00:00
( f2fl ( xc1 ) + canvas . cv_bitmap . bm_x + 0.5 ) / static_cast < float > ( last_width ) ,
1.0 - ( f2fl ( yc1 ) + canvas . cv_bitmap . bm_y + 0.5 ) / static_cast < float > ( last_height ) , 0 ) ;
2007-02-20 00:00:28 +00:00
glScalef ( f2fl ( r1 ) / last_width , f2fl ( r1 ) / last_height , 1.0 ) ;
2016-06-05 01:04:26 +00:00
nsides = 10 + 2 * static_cast < int > ( M_PI * f2fl ( r1 ) / 19 ) ;
2011-02-09 16:18:26 +00:00
if ( ! circle_va )
circle_va = circle_array_init ( nsides ) ;
2014-08-05 02:32:35 +00:00
ogl_drawcircle ( nsides , GL_LINE_LOOP , circle_va . get ( ) ) ;
2006-03-20 16:43:15 +00:00
glPopMatrix ( ) ;
return 0 ;
}
2007-06-10 16:21:53 +00:00
2016-12-29 03:27:13 +00:00
int gr_disk ( grs_canvas & canvas , const fix x , const fix y , const fix r , const uint8_t c )
2011-01-10 15:12:00 +00:00
{
2016-02-12 04:02:28 +00:00
int nsides ;
2011-01-10 15:12:00 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2016-12-29 03:27:13 +00:00
glColor4f ( CPAL2Tr ( c ) , CPAL2Tg ( c ) , CPAL2Tb ( c ) , ( canvas . cv_fade_level > = GR_FADE_OFF ) ? 1.0 : 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ) ;
2011-01-10 15:12:00 +00:00
glPushMatrix ( ) ;
glTranslatef (
2016-12-29 03:27:13 +00:00
( f2fl ( x ) + canvas . cv_bitmap . bm_x + 0.5 ) / static_cast < float > ( last_width ) ,
1.0 - ( f2fl ( y ) + canvas . cv_bitmap . bm_y + 0.5 ) / static_cast < float > ( last_height ) , 0 ) ;
2011-01-10 15:12:00 +00:00
glScalef ( f2fl ( r ) / last_width , f2fl ( r ) / last_height , 1.0 ) ;
2016-06-05 01:04:26 +00:00
nsides = 10 + 2 * static_cast < int > ( M_PI * f2fl ( r ) / 19 ) ;
2011-02-09 16:18:26 +00:00
if ( ! disk_va )
disk_va = circle_array_init ( nsides ) ;
2014-08-05 02:32:35 +00:00
ogl_drawcircle ( nsides , GL_TRIANGLE_FAN , disk_va . get ( ) ) ;
2011-01-10 15:12:00 +00:00
glPopMatrix ( ) ;
return 0 ;
}
2011-01-06 11:43:55 +00:00
/*
* Draw flat - shaded Polygon ( Lasers , Drone - arms , Driller - ears )
*/
2017-03-18 18:07:35 +00:00
void _g3_draw_poly ( grs_canvas & canvas , const uint_fast32_t nv , cg3s_point * const * const pointlist , const uint8_t palette_color_index )
2006-03-20 16:43:15 +00:00
{
2020-06-10 02:25:33 +00:00
if ( nv > MAX_POINTS_PER_POLY )
return ;
flatten_array < GLfloat , 4 , MAX_POINTS_PER_POLY > color_array ;
flatten_array < GLfloat , 3 , MAX_POINTS_PER_POLY > vertices ;
2011-01-06 11:43:55 +00:00
2011-09-26 21:00:23 +00:00
r_polyc + + ;
2016-01-09 16:38:10 +00:00
ogl_client_states < int , GL_VERTEX_ARRAY , GL_COLOR_ARRAY > cs ;
2006-03-20 16:43:15 +00:00
OGL_DISABLE ( TEXTURE_2D ) ;
2016-05-22 17:49:31 +00:00
const float color_r = PAL2Tr ( palette_color_index ) , color_g = PAL2Tg ( palette_color_index ) , color_b = PAL2Tb ( palette_color_index ) ;
2011-01-06 11:43:55 +00:00
2017-02-11 21:42:41 +00:00
const float color_a = ( canvas . cv_fade_level > = GR_FADE_OFF )
2016-05-22 17:49:31 +00:00
? 1.0
2017-02-11 21:42:41 +00:00
: 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ;
2011-01-06 11:43:55 +00:00
2020-06-10 02:25:33 +00:00
for ( auto & & [ p , v , c ] : zip (
unchecked_partial_range ( pointlist , nv ) ,
unchecked_partial_range ( vertices . nested . data ( ) , nv ) ,
unchecked_partial_range ( color_array . nested . data ( ) , nv )
)
)
2016-02-12 04:02:28 +00:00
{
2020-06-10 02:25:33 +00:00
c [ 0 ] = color_r ;
c [ 1 ] = color_g ;
c [ 2 ] = color_b ;
c [ 3 ] = color_a ;
auto & pv = p - > p3_vec ;
v [ 0 ] = f2glf ( pv . x ) ;
v [ 1 ] = f2glf ( pv . y ) ;
v [ 2 ] = - f2glf ( pv . z ) ;
2006-03-20 16:43:15 +00:00
}
2011-01-06 11:43:55 +00:00
2020-06-10 02:25:33 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , vertices . flat . data ( ) ) ;
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . flat . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , nv ) ;
2006-03-20 16:43:15 +00:00
}
2011-01-06 11:43:55 +00:00
/*
* Everything texturemapped ( walls , robots , ship )
*/
2017-02-11 21:42:39 +00:00
void _g3_draw_tmap ( grs_canvas & canvas , const unsigned nv , cg3s_point * const * const pointlist , const g3s_uvl * const uvl_list , const g3s_lrgb * const light_rgb , grs_bitmap & bm )
2006-03-20 16:43:15 +00:00
{
2013-12-08 18:22:17 +00:00
GLfloat color_alpha = 1.0 ;
2011-09-26 21:00:23 +00:00
2016-01-09 16:38:10 +00:00
ogl_client_states < int , GL_VERTEX_ARRAY , GL_COLOR_ARRAY > cs ;
2011-01-06 11:43:55 +00:00
if ( tmap_drawer_ptr = = draw_tmap ) {
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2006-03-20 16:43:15 +00:00
OGL_ENABLE ( TEXTURE_2D ) ;
2016-09-17 16:26:59 +00:00
ogl_bindbmtex ( bm , 0 ) ;
2014-11-13 03:44:04 +00:00
ogl_texwrap ( bm . gltexture , GL_REPEAT ) ;
2011-01-06 11:43:55 +00:00
r_tpolyc + + ;
2017-02-11 21:42:39 +00:00
color_alpha = ( canvas . cv_fade_level > = GR_FADE_OFF ) ? 1.0 : ( 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ) ;
2011-01-06 11:43:55 +00:00
} else if ( tmap_drawer_ptr = = draw_tmap_flat ) {
OGL_DISABLE ( TEXTURE_2D ) ;
/* for cloaked state faces */
2017-02-11 21:42:39 +00:00
color_alpha = 1.0 - ( canvas . cv_fade_level / static_cast < GLfloat > ( NUM_LIGHTING_LEVELS ) ) ;
2011-01-06 11:43:55 +00:00
} else {
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " g3_draw_tmap: unhandled tmap_drawer " ) ) ;
2014-08-16 17:35:44 +00:00
return ;
2006-03-20 16:43:15 +00:00
}
2011-09-26 21:00:23 +00:00
2020-05-22 02:40:26 +00:00
flatten_array < GLfloat , 3 , MAX_POINTS_PER_POLY > vertices ;
flatten_array < GLfloat , 4 , MAX_POINTS_PER_POLY > color_array ;
flatten_array < GLfloat , 2 , MAX_POINTS_PER_POLY > texcoord_array ;
for ( auto & & [ point , light , uvl , vert , color , texcoord ] : zip (
unchecked_partial_range ( pointlist , nv ) ,
unchecked_partial_range ( light_rgb , nv ) ,
unchecked_partial_range ( uvl_list , nv ) ,
unchecked_partial_range ( vertices . nested . data ( ) , nv ) ,
unchecked_partial_range ( color_array . nested . data ( ) , nv ) ,
partial_range ( texcoord_array . nested , nv )
)
)
{
vert [ 0 ] = f2glf ( point - > p3_vec . x ) ;
vert [ 1 ] = f2glf ( point - > p3_vec . y ) ;
vert [ 2 ] = - f2glf ( point - > p3_vec . z ) ;
color [ 3 ] = color_alpha ;
2011-01-06 11:43:55 +00:00
if ( tmap_drawer_ptr = = draw_tmap_flat ) {
2020-05-22 02:40:26 +00:00
color [ 0 ] = color [ 1 ] = color [ 2 ] = 0 ;
}
else
{
if ( bm . get_flag_mask ( BM_FLAG_NO_LIGHTING ) )
{
color [ 0 ] = color [ 1 ] = color [ 2 ] = 1.0 ;
}
else
{
color [ 0 ] = f2glf ( light . r ) ;
color [ 1 ] = f2glf ( light . g ) ;
color [ 2 ] = f2glf ( light . b ) ;
}
texcoord [ 0 ] = f2glf ( uvl . u ) ;
texcoord [ 1 ] = f2glf ( uvl . v ) ;
2011-01-06 11:43:55 +00:00
}
}
2020-05-22 02:40:26 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , vertices . flat . data ( ) ) ;
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . flat . data ( ) ) ;
2011-01-06 11:43:55 +00:00
if ( tmap_drawer_ptr = = draw_tmap ) {
2020-05-22 02:40:26 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , 0 , texcoord_array . flat . data ( ) ) ;
2011-01-06 11:43:55 +00:00
}
glDrawArrays ( GL_TRIANGLE_FAN , 0 , nv ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
glDisableClientState ( GL_COLOR_ARRAY ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2006-03-20 16:43:15 +00:00
}
2015-12-05 22:57:24 +00:00
}
2011-01-06 11:43:55 +00:00
/*
* Everything texturemapped with secondary texture ( walls with secondary texture )
*/
2020-08-24 01:31:28 +00:00
void _g3_draw_tmap_2 ( grs_canvas & canvas , const unsigned nv , const g3s_point * const * const pointlist , const g3s_uvl * uvl_list , const g3s_lrgb * light_rgb , grs_bitmap & bmbot , grs_bitmap & bm , const texture2_rotation_low orient )
2007-06-10 16:21:53 +00:00
{
2017-02-11 21:42:41 +00:00
_g3_draw_tmap ( canvas , nv , pointlist , uvl_list , light_rgb , bmbot ) ; //draw the bottom texture first.. could be optimized with multitexturing..
2016-01-09 16:38:10 +00:00
ogl_client_states < int , GL_VERTEX_ARRAY , GL_COLOR_ARRAY , GL_TEXTURE_COORD_ARRAY > cs ;
2020-06-10 02:25:33 +00:00
( void ) cs ;
2007-06-10 16:21:53 +00:00
r_tpolyc + + ;
OGL_ENABLE ( TEXTURE_2D ) ;
2017-02-11 21:42:41 +00:00
ogl_bindbmtex ( bm , 1 ) ;
ogl_texwrap ( bm . gltexture , GL_REPEAT ) ;
2017-02-11 21:42:41 +00:00
2020-06-10 02:25:33 +00:00
flatten_array < GLfloat , 4 , MAX_POINTS_PER_POLY > color_array ;
2017-02-11 21:42:41 +00:00
{
2017-02-11 21:42:41 +00:00
const GLfloat alpha = ( canvas . cv_fade_level > = GR_FADE_OFF )
2017-02-11 21:42:41 +00:00
? 1.0
2017-02-11 21:42:41 +00:00
: ( 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ) ;
2020-06-10 02:25:33 +00:00
auto & & color_range = unchecked_partial_range ( color_array . nested . data ( ) , nv ) ;
2017-02-11 21:42:41 +00:00
if ( bm . get_flag_mask ( BM_FLAG_NO_LIGHTING ) )
2017-02-11 21:42:41 +00:00
{
2020-06-10 02:25:33 +00:00
for ( auto & e : color_range )
2017-02-11 21:42:41 +00:00
{
2020-06-10 02:25:33 +00:00
e [ 0 ] = e [ 1 ] = e [ 2 ] = 1.0 ;
e [ 3 ] = alpha ;
2017-02-11 21:42:41 +00:00
}
}
else
{
2020-06-10 02:25:33 +00:00
for ( auto & & [ e , l ] : zip (
color_range ,
unchecked_partial_range ( light_rgb , nv )
)
)
2017-02-11 21:42:41 +00:00
{
2020-06-10 02:25:33 +00:00
e [ 0 ] = f2glf ( l . r ) ;
e [ 1 ] = f2glf ( l . g ) ;
e [ 2 ] = f2glf ( l . b ) ;
e [ 3 ] = alpha ;
2017-02-11 21:42:41 +00:00
}
}
}
2020-06-10 02:25:33 +00:00
flatten_array < GLfloat , 3 , MAX_POINTS_PER_POLY > vertices ;
flatten_array < GLfloat , 2 , MAX_POINTS_PER_POLY > texcoord_array ;
2017-02-11 21:42:41 +00:00
2020-06-10 02:25:33 +00:00
for ( auto & & [ point , uvl , vert , texcoord ] : zip (
unchecked_partial_range ( pointlist , nv ) ,
unchecked_partial_range ( uvl_list , nv ) ,
unchecked_partial_range ( vertices . nested . data ( ) , nv ) ,
partial_range ( texcoord_array . nested , nv )
)
)
{
const GLfloat uf = f2glf ( uvl . u ) , vf = f2glf ( uvl . v ) ;
2007-06-10 16:21:53 +00:00
switch ( orient ) {
2020-08-24 01:31:28 +00:00
case texture2_rotation_low : : _1 :
2020-06-10 02:25:33 +00:00
texcoord [ 0 ] = 1.0 - vf ;
texcoord [ 1 ] = uf ;
2007-06-10 16:21:53 +00:00
break ;
2020-08-24 01:31:28 +00:00
case texture2_rotation_low : : _2 :
2020-06-10 02:25:33 +00:00
texcoord [ 0 ] = 1.0 - uf ;
texcoord [ 1 ] = 1.0 - vf ;
2007-06-10 16:21:53 +00:00
break ;
2020-08-24 01:31:28 +00:00
case texture2_rotation_low : : _3 :
2020-06-10 02:25:33 +00:00
texcoord [ 0 ] = vf ;
texcoord [ 1 ] = 1.0 - uf ;
2007-06-10 16:21:53 +00:00
break ;
default :
2020-06-10 02:25:33 +00:00
texcoord [ 0 ] = uf ;
texcoord [ 1 ] = vf ;
2007-06-10 16:21:53 +00:00
break ;
2006-03-20 16:43:15 +00:00
}
2020-06-10 02:25:33 +00:00
vert [ 0 ] = f2glf ( point - > p3_vec . x ) ;
vert [ 1 ] = f2glf ( point - > p3_vec . y ) ;
vert [ 2 ] = - f2glf ( point - > p3_vec . z ) ;
2006-03-20 16:43:15 +00:00
}
2020-06-10 02:25:33 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , vertices . flat . data ( ) ) ;
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . flat . data ( ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , texcoord_array . flat . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , nv ) ;
2006-03-20 16:43:15 +00:00
}
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:24 +00:00
2011-01-06 11:43:55 +00:00
/*
* 2 d Sprites ( Fireaballs , powerups , explosions ) . NOT hostages
*/
2017-02-11 21:42:42 +00:00
void g3_draw_bitmap ( grs_canvas & canvas , const vms_vector & pos , const fix iwidth , const fix iheight , grs_bitmap & bm )
2006-03-20 16:43:15 +00:00
{
r_bitmapc + + ;
2011-01-06 11:43:55 +00:00
2016-01-09 16:38:10 +00:00
ogl_client_states < int , GL_VERTEX_ARRAY , GL_COLOR_ARRAY , GL_TEXTURE_COORD_ARRAY > cs ;
auto & i = std : : get < 0 > ( cs ) ;
2009-11-30 19:11:46 +00:00
2006-03-20 16:43:15 +00:00
OGL_ENABLE ( TEXTURE_2D ) ;
2016-09-17 13:56:43 +00:00
ogl_bindbmtex ( bm , 0 ) ;
2014-11-30 22:09:17 +00:00
ogl_texwrap ( bm . gltexture , GL_CLAMP_TO_EDGE ) ;
2009-11-30 19:11:46 +00:00
2015-04-02 02:36:56 +00:00
const auto width = fixmul ( iwidth , Matrix_scale . x ) ;
const auto height = fixmul ( iheight , Matrix_scale . y ) ;
2015-04-02 02:36:56 +00:00
constexpr unsigned point_count = 4 ;
struct fvertex_t
{
GLfloat x , y , z ;
} ;
struct fcolor_t
{
GLfloat r , g , b , a ;
} ;
struct ftexcoord_t
{
GLfloat u , v ;
} ;
2020-05-02 21:18:42 +00:00
std : : array < fvertex_t , point_count > vertices ;
std : : array < fcolor_t , point_count > color_array ;
std : : array < ftexcoord_t , point_count > texcoord_array ;
2015-04-02 02:36:56 +00:00
const auto & v1 = vm_vec_sub ( pos , View_position ) ;
const auto & rpv = vm_vec_rotate ( v1 , View_matrix ) ;
const auto bmglu = bm . gltexture - > u ;
const auto bmglv = bm . gltexture - > v ;
2017-02-11 21:42:42 +00:00
const auto alpha = canvas . cv_fade_level > = GR_FADE_OFF ? 1.0 : ( 1.0 - static_cast < float > ( canvas . cv_fade_level ) / ( static_cast < float > ( GR_FADE_LEVELS ) - 1.0 ) ) ;
2015-04-02 02:36:56 +00:00
const auto vert_z = - f2glf ( rpv . z ) ;
2006-03-20 16:43:15 +00:00
for ( i = 0 ; i < 4 ; i + + ) {
2015-04-02 02:36:56 +00:00
auto pv = rpv ;
2006-03-20 16:43:15 +00:00
switch ( i ) {
case 0 :
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . u = 0.0 ;
texcoord_array [ i ] . v = 0.0 ;
2006-03-20 16:43:15 +00:00
pv . x + = - width ;
pv . y + = height ;
break ;
case 1 :
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . u = bmglu ;
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . v = 0.0 ;
2006-03-20 16:43:15 +00:00
pv . x + = width ;
pv . y + = height ;
break ;
case 2 :
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . u = bmglu ;
texcoord_array [ i ] . v = bmglv ;
2006-03-20 16:43:15 +00:00
pv . x + = width ;
pv . y + = - height ;
break ;
case 3 :
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . u = 0.0 ;
2015-04-02 02:36:56 +00:00
texcoord_array [ i ] . v = bmglv ;
2006-03-20 16:43:15 +00:00
pv . x + = - width ;
pv . y + = - height ;
break ;
}
2009-11-30 19:11:46 +00:00
2015-04-02 02:36:56 +00:00
color_array [ i ] . r = 1.0 ;
color_array [ i ] . g = 1.0 ;
color_array [ i ] . b = 1.0 ;
2015-04-02 02:36:56 +00:00
color_array [ i ] . a = alpha ;
2017-07-08 18:17:49 +00:00
vertices [ i ] . x = f2glf ( pv . x ) ;
vertices [ i ] . y = f2glf ( pv . y ) ;
vertices [ i ] . z = vert_z ;
2006-03-20 16:43:15 +00:00
}
2017-07-08 18:17:49 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , vertices . data ( ) ) ;
2015-04-02 02:36:56 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . data ( ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , texcoord_array . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ; // Replaced GL_QUADS
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2011-01-06 11:43:55 +00:00
/*
* Movies
2011-01-16 00:50:28 +00:00
* Since this function will create a new texture each call , mipmapping can be very GPU intensive - so it has an optional setting for texture filtering .
2011-01-06 11:43:55 +00:00
*/
2021-01-17 22:23:23 +00:00
bool ogl_ubitblt_i ( unsigned dw , unsigned dh , unsigned dx , unsigned dy , unsigned sw , unsigned sh , unsigned sx , unsigned sy , const grs_bitmap & src , grs_bitmap & dest , const opengl_texture_filter texfilt )
2006-03-20 16:43:15 +00:00
{
2011-01-06 11:43:55 +00:00
GLfloat xo , yo , xs , ys , u1 , v1 ;
GLfloat color_array [ ] = { 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 } ;
GLfloat texcoord_array [ ] = { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 } ;
2017-07-08 18:17:49 +00:00
GLfloat vertices [ ] = { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 } ;
2016-01-09 16:38:10 +00:00
struct bitblt_free_ogl_texture
{
ogl_texture t ;
~ bitblt_free_ogl_texture ( )
{
ogl_freetexture ( t ) ;
}
} ;
ogl_client_states < bitblt_free_ogl_texture , GL_VERTEX_ARRAY , GL_COLOR_ARRAY , GL_TEXTURE_COORD_ARRAY > cs ;
ogl_texture & tex = std : : get < 0 > ( cs ) . t ;
2006-03-20 16:43:15 +00:00
r_ubitbltc + + ;
2014-11-30 22:09:19 +00:00
ogl_init_texture ( tex , sw , sh , OGL_FLAG_ALPHA ) ;
2007-06-10 16:21:53 +00:00
tex . prio = 0.0 ;
2014-12-02 03:35:01 +00:00
tex . lw = src . bm_rowsize ;
2006-03-20 16:43:15 +00:00
u1 = v1 = 0 ;
2014-12-02 03:35:01 +00:00
dx + = dest . bm_x ;
dy + = dest . bm_y ;
2016-06-05 01:04:26 +00:00
xo = dx / static_cast < float > ( last_width ) ;
xs = dw / static_cast < float > ( last_width ) ;
yo = 1.0 - dy / static_cast < float > ( last_height ) ;
ys = dh / static_cast < float > ( last_height ) ;
2006-03-20 16:43:15 +00:00
OGL_ENABLE ( TEXTURE_2D ) ;
2017-01-15 00:03:13 +00:00
ogl_loadtexture ( gr_current_pal , src . get_bitmap_data ( ) , sx , sy , tex , src . get_flags ( ) , 0 , texfilt , 0 , 0 ) ;
2006-03-20 16:43:15 +00:00
OGL_BINDTEXTURE ( tex . handle ) ;
2008-02-24 14:41:27 +00:00
ogl_texwrap ( & tex , GL_CLAMP_TO_EDGE ) ;
2006-03-20 16:43:15 +00:00
2017-07-08 18:17:49 +00:00
vertices [ 0 ] = xo ;
vertices [ 1 ] = yo ;
vertices [ 2 ] = xo + xs ;
vertices [ 3 ] = yo ;
vertices [ 4 ] = xo + xs ;
vertices [ 5 ] = yo - ys ;
vertices [ 6 ] = xo ;
vertices [ 7 ] = yo - ys ;
2011-01-06 11:43:55 +00:00
texcoord_array [ 0 ] = u1 ;
texcoord_array [ 1 ] = v1 ;
texcoord_array [ 2 ] = tex . u ;
texcoord_array [ 3 ] = v1 ;
texcoord_array [ 4 ] = tex . u ;
texcoord_array [ 5 ] = tex . v ;
texcoord_array [ 6 ] = u1 ;
texcoord_array [ 7 ] = tex . v ;
2017-07-08 18:17:49 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , vertices ) ;
2011-01-06 11:43:55 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , color_array ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , texcoord_array ) ;
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ; //replaced GL_QUADS
2006-03-20 16:43:15 +00:00
return 0 ;
}
2007-06-10 16:21:53 +00:00
2014-12-02 03:35:01 +00:00
bool ogl_ubitblt ( unsigned w , unsigned h , unsigned dx , unsigned dy , unsigned sx , unsigned sy , const grs_bitmap & src , grs_bitmap & dest ) {
2021-01-17 22:23:23 +00:00
return ogl_ubitblt_i ( w , h , dx , dy , w , h , sx , sy , src , dest , opengl_texture_filter : : classic ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2011-02-23 16:46:36 +00:00
/*
* set depth testing on or off
*/
2011-02-17 23:17:49 +00:00
void ogl_toggle_depth_test ( int enable )
{
if ( enable )
glEnable ( GL_DEPTH_TEST ) ;
else
glDisable ( GL_DEPTH_TEST ) ;
}
2011-02-23 16:46:36 +00:00
/*
* set blending function
*/
2017-03-18 18:07:36 +00:00
void ogl_set_blending ( const gr_blend cv_blend_func )
2011-02-23 16:46:36 +00:00
{
2016-02-12 04:02:28 +00:00
GLenum s , d ;
2016-02-12 04:02:28 +00:00
switch ( cv_blend_func )
2011-02-23 16:46:36 +00:00
{
2020-07-16 02:31:04 +00:00
case gr_blend : : additive_a :
2016-02-12 04:02:28 +00:00
s = GL_SRC_ALPHA ;
d = GL_ONE ;
2011-02-23 16:46:36 +00:00
break ;
2020-07-16 02:31:04 +00:00
case gr_blend : : additive_c :
2016-02-12 04:02:28 +00:00
s = GL_ONE ;
d = GL_ONE ;
2011-02-23 16:46:36 +00:00
break ;
2020-07-16 02:31:04 +00:00
case gr_blend : : normal :
2011-02-23 16:46:36 +00:00
default :
2016-02-12 04:02:28 +00:00
s = GL_SRC_ALPHA ;
d = GL_ONE_MINUS_SRC_ALPHA ;
2011-02-23 16:46:36 +00:00
break ;
}
2016-02-12 04:02:28 +00:00
glBlendFunc ( s , d ) ;
2011-02-23 16:46:36 +00:00
}
2017-02-11 21:42:33 +00:00
void ogl_start_frame ( grs_canvas & canvas )
{
2015-12-04 03:36:32 +00:00
r_polyc = 0 ; r_tpolyc = 0 ; r_bitmapc = 0 ; r_ubitbltc = 0 ;
2006-03-20 16:43:15 +00:00
2021-03-09 20:59:20 +00:00
OGL_VIEWPORT ( canvas . cv_bitmap . bm_x , canvas . cv_bitmap . bm_y , canvas . cv_bitmap . bm_w / 2 , canvas . cv_bitmap . bm_h ) ;
2006-03-20 16:43:15 +00:00
glClearColor ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
2006-05-05 13:23:53 +00:00
2008-11-09 14:31:30 +00:00
glLineWidth ( linedotscale ) ;
2006-05-05 13:23:53 +00:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glEnable ( GL_ALPHA_TEST ) ;
2006-07-11 16:13:47 +00:00
glAlphaFunc ( GL_GEQUAL , 0.02 ) ;
2006-05-05 13:23:53 +00:00
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_LEQUAL ) ;
2006-07-11 16:13:47 +00:00
2006-05-05 13:23:53 +00:00
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2006-07-11 16:13:47 +00:00
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;
2006-05-05 13:23:53 +00:00
2006-03-20 16:43:15 +00:00
glShadeModel ( GL_SMOOTH ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ; //clear matrix
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES
2011-02-17 23:43:03 +00:00
perspective ( 90.0 , 1.0 , 0.1 , 5000.0 ) ;
2011-01-06 11:43:55 +00:00
# else
2011-02-17 23:43:03 +00:00
gluPerspective ( 90.0 , 1.0 , 0.1 , 5000.0 ) ;
2011-01-06 11:43:55 +00:00
# endif
2006-03-20 16:43:15 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ; //clear matrix
2021-03-09 20:59:20 +00:00
glGetFloatv ( GL_PROJECTION_MATRIX , & ogl_stereo_transform [ 0 ] [ 0 ] ) ;
glGetFloatv ( GL_PROJECTION_MATRIX , & ogl_stereo_transform [ 1 ] [ 0 ] ) ;
glGetIntegerv ( GL_VIEWPORT , & ogl_stereo_viewport [ 0 ] [ 0 ] ) ;
glGetIntegerv ( GL_VIEWPORT , & ogl_stereo_viewport [ 1 ] [ 0 ] ) ;
// query if stereo quad buffering available?
glGetBooleanv ( GL_STEREO , & ogl_stereo_enabled ) ;
// half-height viewports for above/below format
// ogl_stereo_viewport[0][1] = // y/2
// ogl_stereo_viewport[0][3] = // h/2
// ogl_stereo_viewport[1][3];// /= 2; // h/2
// half-width viewports for side-by-side format
ogl_stereo_viewport [ 1 ] [ 0 ] = // x/2
ogl_stereo_viewport [ 0 ] [ 2 ] = // w/2
ogl_stereo_viewport [ 1 ] [ 2 ] ; // /= 2; // w/2
}
void ogl_set_frame ( int xeye , int xoff )
{
( void ) xoff ;
if ( xeye < 0 ) {
// left eye view
if ( ogl_stereo_enabled )
glDrawBuffer ( GL_BACK_LEFT ) ;
else
glViewport ( ogl_stereo_viewport [ 0 ] [ 0 ] , ogl_stereo_viewport [ 0 ] [ 1 ] , ogl_stereo_viewport [ 0 ] [ 2 ] , ogl_stereo_viewport [ 0 ] [ 3 ] ) ;
glMatrixMode ( GL_PROJECTION ) ;
// ogl_stereo_transform[0][2] += xeye; // xeye < 0
// ogl_stereo_transform[0][3] -= xoff; // xoff < 0
glLoadMatrixf ( & ogl_stereo_transform [ 0 ] [ 0 ] ) ;
glMatrixMode ( GL_MODELVIEW ) ;
}
else if ( xeye > 0 ) {
// right eye view
if ( ogl_stereo_enabled )
glDrawBuffer ( GL_BACK_RIGHT ) ;
else
glViewport ( ogl_stereo_viewport [ 1 ] [ 0 ] , ogl_stereo_viewport [ 1 ] [ 1 ] , ogl_stereo_viewport [ 1 ] [ 2 ] , ogl_stereo_viewport [ 1 ] [ 3 ] ) ;
glMatrixMode ( GL_PROJECTION ) ;
// ogl_stereo_transform[1][2] += xeye; // xeye > 0
// ogl_stereo_transform[1][3] += xoff; // xoff < 0
glLoadMatrixf ( & ogl_stereo_transform [ 1 ] [ 0 ] ) ;
glMatrixMode ( GL_MODELVIEW ) ;
}
2006-03-20 16:43:15 +00:00
}
2006-05-05 13:23:53 +00:00
2006-03-20 16:43:15 +00:00
void ogl_end_frame ( void ) {
2015-03-22 18:49:21 +00:00
OGL_VIEWPORT ( 0 , 0 , grd_curscreen - > get_screen_width ( ) , grd_curscreen - > get_screen_height ( ) ) ;
2006-03-20 16:43:15 +00:00
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ; //clear matrix
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES
2011-01-06 11:43:55 +00:00
glOrthof ( 0.0 , 1.0 , 0.0 , 1.0 , - 1.0 , 1.0 ) ;
# else
2006-03-20 16:43:15 +00:00
glOrtho ( 0.0 , 1.0 , 0.0 , 1.0 , - 1.0 , 1.0 ) ;
2011-01-06 11:43:55 +00:00
# endif
2006-03-20 16:43:15 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ; //clear matrix
2006-07-16 15:54:30 +00:00
glDisable ( GL_CULL_FACE ) ;
2006-05-05 13:23:53 +00:00
glDisable ( GL_DEPTH_TEST ) ;
2006-03-20 16:43:15 +00:00
}
2007-03-22 14:15:46 +00:00
2007-06-10 16:21:53 +00:00
void gr_flip ( void )
{
2015-12-24 04:01:28 +00:00
if ( CGameArg . DbgRenderStats )
2008-10-28 17:04:35 +00:00
ogl_texture_stats ( ) ;
2007-07-18 20:13:17 +00:00
2006-03-20 16:43:15 +00:00
ogl_do_palfx ( ) ;
ogl_swap_buffers_internal ( ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
}
2006-10-17 18:14:56 +00:00
//little hack to find the nearest bigger power of 2 for a given number
2013-08-16 02:00:35 +00:00
unsigned pow2ize ( unsigned f0 ) {
unsigned f1 = ( f0 - 1 ) | 1 ;
for ( unsigned i = 4 ; i - - > 0 ; )
f1 | = f1 > > ( 1 < < i ) ;
unsigned f2 = f1 + 1 ;
assert ( f2 > = f0 ) ;
assert ( ! ( f2 & f1 ) ) ;
assert ( ( f2 > > 1 ) < f0 ) ;
return f2 ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2007-01-09 01:23:49 +00:00
// Allocate the pixel buffers 'pixels' and 'texbuf' based on current screen resolution
2013-08-13 23:11:49 +00:00
void ogl_init_pixel_buffers ( unsigned w , unsigned h )
2007-01-09 01:23:49 +00:00
{
2007-06-10 16:21:53 +00:00
w = pow2ize ( w ) ; // convert to OpenGL texture size
2007-01-09 01:23:49 +00:00
h = pow2ize ( h ) ;
2020-05-02 21:18:42 +00:00
texbuf = std : : make_unique < GLubyte [ ] > ( max ( w , 1024u ) * max ( h , 256u ) * 4 ) ; // must also fit big font texture
2007-01-09 01:23:49 +00:00
}
void ogl_close_pixel_buffers ( void )
{
2014-08-05 02:33:10 +00:00
texbuf . reset ( ) ;
2007-01-09 01:23:49 +00:00
}
2018-02-01 05:38:47 +00:00
static void ogl_filltexbuf ( const palette_array_t & pal , const uint8_t * const data , GLubyte * texp , const unsigned truewidth , const unsigned width , const unsigned height , const int dxo , const int dyo , const unsigned twidth , const unsigned theight , const int type , const int bm_flags , const int data_format )
2006-03-20 16:43:15 +00:00
{
2015-03-22 18:49:21 +00:00
if ( ( width > max ( static_cast < unsigned > ( grd_curscreen - > get_screen_width ( ) ) , 1024u ) ) | |
( height > max ( static_cast < unsigned > ( grd_curscreen - > get_screen_height ( ) ) , 256u ) ) )
2007-06-10 16:21:53 +00:00
Error ( " Texture is too big: %ix%i " , width , height ) ;
2006-03-20 16:43:15 +00:00
2013-08-13 23:11:49 +00:00
for ( unsigned y = 0 ; y < theight ; y + + )
2008-04-19 19:11:32 +00:00
{
2013-08-13 23:11:49 +00:00
int i = dxo + truewidth * ( y + dyo ) ;
for ( unsigned x = 0 ; x < twidth ; x + + )
2008-04-19 19:11:32 +00:00
{
2013-08-13 23:11:49 +00:00
int c ;
2006-03-20 16:43:15 +00:00
if ( x < width & & y < height )
2008-02-24 14:41:27 +00:00
{
2007-06-10 16:21:53 +00:00
if ( data_format )
{
int j ;
for ( j = 0 ; j < data_format ; + + j )
( * ( texp + + ) ) = data [ i * data_format + j ] ;
i + + ;
continue ;
}
else
2008-02-24 14:41:27 +00:00
{
2007-06-10 16:21:53 +00:00
c = data [ i + + ] ;
2008-02-24 14:41:27 +00:00
}
}
2011-01-17 14:00:13 +00:00
else if ( x = = width & & y < height ) // end of bitmap reached - fill this pixel with last color to make a clean border when filtering this texture
2011-01-16 18:33:30 +00:00
{
c = data [ ( width * ( y + 1 ) ) - 1 ] ;
}
2011-01-17 14:00:13 +00:00
else if ( y = = height & & x < width ) // end of bitmap reached - fill this row with color or last row to make a clean border when filtering this texture
2011-01-16 18:33:30 +00:00
{
c = data [ ( width * ( height - 1 ) ) + x ] ;
}
2006-03-20 16:43:15 +00:00
else
2008-02-24 14:41:27 +00:00
{
2007-06-10 16:21:53 +00:00
c = 256 ; // fill the pad space with transparency (or blackness)
2008-02-24 14:41:27 +00:00
}
2007-06-10 16:21:53 +00:00
if ( c = = 254 & & ( bm_flags & BM_FLAG_SUPER_TRANSPARENT ) )
{
switch ( type )
{
2008-04-19 19:11:32 +00:00
case GL_RGBA :
( * ( texp + + ) ) = 255 ;
( * ( texp + + ) ) = 255 ;
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2017-07-08 18:17:49 +00:00
case GL_LUMINANCE_ALPHA :
2008-04-19 19:11:32 +00:00
( * ( texp + + ) ) = 255 ;
( * ( texp + + ) ) = 0 ; // transparent pixel
break ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2008-04-19 19:11:32 +00:00
case GL_COLOR_INDEX :
( * ( texp + + ) ) = c ;
break ;
2011-01-06 11:43:55 +00:00
# endif
2008-04-19 19:11:32 +00:00
default :
Error ( " ogl_filltexbuf unhandled super-transparent texformat \n " ) ;
break ;
2007-06-10 16:21:53 +00:00
}
}
2008-10-28 13:28:10 +00:00
else if ( ( c = = 255 & & ( bm_flags & BM_FLAG_TRANSPARENT ) ) | | c = = 256 )
2007-06-10 16:21:53 +00:00
{
2008-04-19 19:11:32 +00:00
switch ( type )
{
2006-03-20 16:43:15 +00:00
case GL_RGBA :
( * ( texp + + ) ) = 0 ;
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2017-07-08 18:17:49 +00:00
case GL_RGB :
2006-03-20 16:43:15 +00:00
( * ( texp + + ) ) = 0 ;
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2017-07-08 18:17:49 +00:00
case GL_LUMINANCE_ALPHA :
2006-03-20 16:43:15 +00:00
( * ( texp + + ) ) = 0 ;
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2017-07-08 18:17:49 +00:00
case GL_LUMINANCE :
2006-03-20 16:43:15 +00:00
( * ( texp + + ) ) = 0 ; //transparent pixel
break ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2007-06-10 16:21:53 +00:00
case GL_COLOR_INDEX :
( * ( texp + + ) ) = c ;
break ;
2011-01-06 11:43:55 +00:00
# endif
2007-06-10 16:21:53 +00:00
default :
Error ( " ogl_filltexbuf unknown texformat \n " ) ;
break ;
2006-03-20 16:43:15 +00:00
}
2008-04-19 19:11:32 +00:00
}
else
{
switch ( type )
{
2006-03-20 16:43:15 +00:00
case GL_LUMINANCE_ALPHA :
( * ( texp + + ) ) = 255 ;
2019-04-04 04:29:03 +00:00
DXX_BOOST_FALLTHROUGH ;
2017-07-08 18:17:49 +00:00
case GL_LUMINANCE : //these could prolly be done to make the intensity based upon the intensity of the resulting color, but its not needed for anything (yet?) so no point. :)
2006-03-20 16:43:15 +00:00
( * ( texp + + ) ) = 255 ;
break ;
2007-06-10 16:21:53 +00:00
case GL_RGB :
2017-01-15 00:03:13 +00:00
( * ( texp + + ) ) = pal [ c ] . r * 4 ;
( * ( texp + + ) ) = pal [ c ] . g * 4 ;
( * ( texp + + ) ) = pal [ c ] . b * 4 ;
2007-06-10 16:21:53 +00:00
break ;
2006-03-20 16:43:15 +00:00
case GL_RGBA :
2017-01-15 00:03:13 +00:00
( * ( texp + + ) ) = pal [ c ] . r * 4 ;
( * ( texp + + ) ) = pal [ c ] . g * 4 ;
( * ( texp + + ) ) = pal [ c ] . b * 4 ;
( * ( texp + + ) ) = 255 ; //not transparent
2007-06-10 16:21:53 +00:00
break ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2007-06-10 16:21:53 +00:00
case GL_COLOR_INDEX :
( * ( texp + + ) ) = c ;
break ;
2011-01-06 11:43:55 +00:00
# endif
2007-06-10 16:21:53 +00:00
default :
Error ( " ogl_filltexbuf unknown texformat \n " ) ;
2006-03-20 16:43:15 +00:00
break ;
}
}
}
}
}
2007-06-10 16:21:53 +00:00
2018-02-01 05:38:47 +00:00
static void tex_set_size1 ( ogl_texture & tex , const unsigned dbits , const unsigned bits , const unsigned w , const unsigned h )
2014-12-02 03:35:01 +00:00
{
2006-03-20 16:43:15 +00:00
int u ;
2014-12-02 03:35:01 +00:00
if ( tex . tw ! = w | | tex . th ! = h ) {
2016-06-05 01:04:26 +00:00
u = ( tex . w / static_cast < float > ( tex . tw ) * w ) * ( tex . h / static_cast < float > ( tex . th ) * h ) ;
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " shrunken texture? " ) ) ;
2006-03-20 16:43:15 +00:00
} else
2014-12-02 03:35:01 +00:00
u = tex . w * tex . h ;
2006-03-20 16:43:15 +00:00
if ( bits < = 0 ) { //the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
2016-06-05 01:04:26 +00:00
tex . bytes = ( static_cast < float > ( w ) * h * dbits ) / 8.0 ;
tex . bytesu = ( static_cast < float > ( u ) * dbits ) / 8.0 ;
2006-03-20 16:43:15 +00:00
} else {
2016-06-05 01:04:26 +00:00
tex . bytes = ( static_cast < float > ( w ) * h * bits ) / 8.0 ;
tex . bytesu = ( static_cast < float > ( u ) * bits ) / 8.0 ;
2006-03-20 16:43:15 +00:00
}
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " tex_set_size1: %ix%i, %ib(%i) %iB " , w , h , bits , dbits , tex . bytes ) ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2014-12-02 03:35:01 +00:00
static void tex_set_size ( ogl_texture & tex )
{
2007-06-10 16:21:53 +00:00
GLint w , h ;
int bi = 16 , a = 0 ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2015-12-18 04:08:24 +00:00
if ( CGameArg . DbgGlGetTexLevelParamOk )
{
2007-06-10 16:21:53 +00:00
GLint t ;
2006-03-20 16:43:15 +00:00
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_WIDTH , & w ) ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_HEIGHT , & h ) ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_LUMINANCE_SIZE , & t ) ; a + = t ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_INTENSITY_SIZE , & t ) ; a + = t ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_RED_SIZE , & t ) ; a + = t ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_GREEN_SIZE , & t ) ; a + = t ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_BLUE_SIZE , & t ) ; a + = t ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_ALPHA_SIZE , & t ) ; a + = t ;
2011-01-06 11:43:55 +00:00
}
else
# endif
{
2014-12-02 03:35:01 +00:00
w = tex . tw ;
h = tex . th ;
2006-03-20 16:43:15 +00:00
}
2014-12-02 03:35:01 +00:00
switch ( tex . format ) {
2006-03-20 16:43:15 +00:00
case GL_LUMINANCE :
bi = 8 ;
break ;
case GL_LUMINANCE_ALPHA :
bi = 8 ;
break ;
2007-06-10 16:21:53 +00:00
case GL_RGB :
2006-03-20 16:43:15 +00:00
case GL_RGBA :
bi = 16 ;
break ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2007-06-10 16:21:53 +00:00
case GL_COLOR_INDEX :
bi = 8 ;
break ;
2011-01-06 11:43:55 +00:00
# endif
2006-03-20 16:43:15 +00:00
default :
2014-12-02 03:35:01 +00:00
throw std : : runtime_error ( " unknown texture format " ) ;
2006-03-20 16:43:15 +00:00
}
2014-12-02 03:35:01 +00:00
tex_set_size1 ( tex , bi , a , w , h ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2006-03-20 16:43:15 +00:00
//loads a palettized bitmap into a ogl RGBA texture.
//Sizes and pads dimensions to multiples of 2 if necessary.
//In theory this could be a problem for repeating textures, but all real
//textures (not sprites, etc) in descent are 64x64, so we are ok.
//stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
2021-01-17 22:23:23 +00:00
static int ogl_loadtexture ( const palette_array_t & pal , const uint8_t * data , const int dxo , int dyo , ogl_texture & tex , const int bm_flags , const int data_format , opengl_texture_filter texfilt , const bool texanis , const bool edgepad )
2007-06-10 16:21:53 +00:00
{
2014-12-02 03:35:01 +00:00
tex . tw = pow2ize ( tex . w ) ;
tex . th = pow2ize ( tex . h ) ; //calculate smallest texture size that can accomodate us (must be multiples of 2)
2006-03-20 16:43:15 +00:00
2007-06-10 16:21:53 +00:00
//calculate u/v values that would make the resulting texture correctly sized
2016-06-05 01:04:26 +00:00
tex . u = static_cast < float > ( static_cast < double > ( tex . w ) / static_cast < double > ( tex . tw ) ) ;
tex . v = static_cast < float > ( static_cast < double > ( tex . h ) / static_cast < double > ( tex . th ) ) ;
2007-06-10 16:21:53 +00:00
2016-08-29 15:07:30 +00:00
auto * bufP = texbuf . get ( ) ;
2014-12-02 03:35:01 +00:00
const uint8_t * outP = texbuf . get ( ) ;
2016-09-26 00:50:09 +00:00
{
2007-06-10 16:21:53 +00:00
if ( bm_flags > = 0 )
2017-01-15 00:03:13 +00:00
ogl_filltexbuf ( pal , data , texbuf . get ( ) , tex . lw , tex . w , tex . h , dxo , dyo , tex . tw , tex . th ,
2014-12-02 03:35:01 +00:00
tex . format , bm_flags , data_format ) ;
2007-06-10 16:21:53 +00:00
else {
2014-12-02 03:35:01 +00:00
if ( ! dxo & & ! dyo & & ( tex . w = = tex . tw ) & & ( tex . h = = tex . th ) )
outP = data ;
2007-06-10 16:21:53 +00:00
else {
int h , w , tw ;
2016-08-29 15:07:30 +00:00
2014-12-02 03:35:01 +00:00
h = tex . lw / tex . w ;
w = ( tex . w - dxo ) * h ;
data + = tex . lw * dyo + h * dxo ;
2016-08-29 15:07:30 +00:00
2014-12-02 03:35:01 +00:00
tw = tex . tw * h ;
2007-06-10 16:21:53 +00:00
h = tw - w ;
2014-12-02 03:35:01 +00:00
for ( ; dyo < tex . h ; dyo + + , data + = tex . lw ) {
2007-06-10 16:21:53 +00:00
memcpy ( bufP , data , w ) ;
bufP + = w ;
memset ( bufP , 0 , h ) ;
bufP + = h ;
}
2014-12-02 03:35:01 +00:00
memset ( bufP , 0 , tex . th * tw - ( bufP - texbuf . get ( ) ) ) ;
2007-06-10 16:21:53 +00:00
}
2008-02-24 14:41:27 +00:00
}
2007-06-10 16:21:53 +00:00
}
2016-08-29 15:07:30 +00:00
//bleed color (rgb) into the alpha area, to deal with "dark edges problem"
2021-01-17 22:23:23 +00:00
if ( tex . format = = GL_RGBA & & texfilt ! = opengl_texture_filter : : classic & & edgepad & & ! CGameArg . OglDarkEdges )
2016-08-29 15:07:30 +00:00
{
GLubyte * p = bufP ;
GLubyte * pdone = p + ( 4 * tex . tw * tex . th ) ;
int line = 4 * tex . tw ;
p + = 4 ;
pdone - = 4 ;
GLubyte * ptop = p + line ;
GLubyte * pbottom = pdone - line ;
for ( ; p < pdone ; p + = 4 )
{
//offsets 0 to 2 are r, g, b. offset 3 is alpha. 0x00 is transparent, 0xff is opaque.
if ( ! * ( p + 3 ) )
{
if ( * ( p - 1 ) )
{
* p = * ( p - 4 ) ;
* ( p + 1 ) = * ( p - 3 ) ;
* ( p + 2 ) = * ( p - 2 ) ;
continue ;
} //from left
if ( * ( p + 7 ) )
{
* p = * ( p + 4 ) ;
* ( p + 1 ) = * ( p + 5 ) ;
* ( p + 2 ) = * ( p + 6 ) ;
continue ;
} //from right
if ( p > = ptop )
{
if ( * ( p - line + 3 ) )
{
* p = * ( p - line ) ;
* ( p + 1 ) = * ( p - line + 1 ) ;
* ( p + 2 ) = * ( p - line + 2 ) ;
continue ;
} //from above
}
if ( p < pbottom )
{
if ( * ( p + line + 3 ) )
{
* p = * ( p + line ) ;
* ( p + 1 ) = * ( p + line + 1 ) ;
* ( p + 2 ) = * ( p + line + 2 ) ;
continue ;
} //from below
if ( * ( p + line - 1 ) )
{
* p = * ( p + line - 4 ) ;
* ( p + 1 ) = * ( p + line - 3 ) ;
* ( p + 2 ) = * ( p + line - 2 ) ;
continue ;
} //bottom left
if ( * ( p + line + 7 ) )
{
* p = * ( p + line + 4 ) ;
* ( p + 1 ) = * ( p + line + 5 ) ;
* ( p + 2 ) = * ( p + line + 6 ) ;
continue ;
} //bottom right
}
if ( p > = ptop )
{
if ( * ( p - line - 1 ) )
{
* p = * ( p - line - 4 ) ;
* ( p + 1 ) = * ( p - line - 3 ) ;
* ( p + 2 ) = * ( p - line - 2 ) ;
continue ;
} //top left
if ( * ( p - line + 7 ) )
{
* p = * ( p - line + 4 ) ;
* ( p + 1 ) = * ( p - line + 5 ) ;
* ( p + 2 ) = * ( p - line + 6 ) ;
continue ;
} //top right
}
}
}
}
2016-08-29 18:53:10 +00:00
int rescale = 1 ;
2021-01-17 22:23:23 +00:00
if ( texfilt = = opengl_texture_filter : : upscale )
2016-08-29 18:53:10 +00:00
{
rescale = 4 ;
if ( ( tex . tw > 256 ) | | ( tex . th > 256 ) )
{
//don't scale big textures, instead "cheat" and render them as normal (nearest)
//these are normally 320x200 and 640x480 images.
//this deals with texture size limits, as well as large textures causing noticeable performance issues/hiccups.
2021-01-17 22:23:23 +00:00
texfilt = opengl_texture_filter : : classic ;
2016-08-29 18:53:10 +00:00
rescale = 1 ;
}
}
GLubyte * buftemp = NULL ;
if ( rescale > 1 )
{
int rebpp = 3 ;
if ( tex . format = = GL_RGBA ) rebpp = 4 ;
if ( tex . format = = GL_LUMINANCE ) rebpp = 1 ;
MALLOC ( buftemp , GLubyte , rescale * tex . tw * rescale * tex . th * rebpp ) ;
int x , y ;
GLubyte * p = buftemp ;
int len = tex . tw * rebpp * rescale ;
int bppscale = ( rebpp * rescale ) ;
for ( y = 0 ; y < tex . th ; y + + )
{
GLubyte * p1 = bufP ;
for ( x = 0 ; x < len ; x + + )
{
* ( p + x ) = * ( outP + ( ( x / bppscale ) * rebpp + ( x % rebpp ) ) ) ;
}
p1 = p ;
p + = len ;
int y2 ;
for ( y2 = 1 ; y2 < rescale ; y2 + + )
{
memcpy ( p , p1 , len ) ;
p + = len ;
}
outP + = tex . tw * rebpp ;
}
outP = buftemp ;
}
2006-03-20 16:43:15 +00:00
// Generate OpenGL texture IDs.
2014-12-02 03:35:01 +00:00
glGenTextures ( 1 , & tex . handle ) ;
2016-09-24 18:06:11 +00:00
# if !DXX_USE_OGLES
2006-03-20 16:43:15 +00:00
//set priority
2014-12-02 03:35:01 +00:00
glPrioritizeTextures ( 1 , & tex . handle , & tex . prio ) ;
2011-01-06 11:43:55 +00:00
# endif
2006-03-20 16:43:15 +00:00
// Give our data to OpenGL.
2014-12-02 03:35:01 +00:00
OGL_BINDTEXTURE ( tex . handle ) ;
2007-06-10 16:21:53 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
2011-01-06 11:43:55 +00:00
2016-08-29 18:53:10 +00:00
// should match structue in menu.cpp
// organized in switches for better readability
bool buildmipmap = false ;
2016-09-03 17:30:18 +00:00
GLint gl_mag_filter_int , gl_min_filter_int ;
2016-08-29 18:53:10 +00:00
switch ( texfilt )
2011-01-06 11:43:55 +00:00
{
2016-08-29 18:53:10 +00:00
default :
2021-01-17 22:23:23 +00:00
case opengl_texture_filter : : classic : // Classic - Nearest
2016-09-03 17:30:18 +00:00
gl_mag_filter_int = GL_NEAREST ;
2016-11-03 20:59:11 +00:00
if ( texanis & & ogl_maxanisotropy > 1.0f )
2016-08-29 18:53:10 +00:00
{
2016-09-03 17:30:18 +00:00
// looks nicer if anisotropy is applied.
gl_min_filter_int = GL_NEAREST_MIPMAP_LINEAR ;
2016-08-29 18:53:10 +00:00
buildmipmap = true ;
}
else
{
2016-09-03 17:30:18 +00:00
gl_min_filter_int = GL_NEAREST ;
2016-08-29 18:53:10 +00:00
buildmipmap = false ;
}
break ;
2021-01-17 22:23:23 +00:00
case opengl_texture_filter : : upscale : // Upscaled - i.e. Blocky Filtered (Bilinear)
case opengl_texture_filter : : trilinear : // Smooth - Trilinear
2016-09-03 17:30:18 +00:00
gl_mag_filter_int = GL_LINEAR ;
gl_min_filter_int = GL_LINEAR_MIPMAP_LINEAR ;
2016-08-29 18:53:10 +00:00
buildmipmap = true ;
break ;
2011-01-06 11:43:55 +00:00
}
2016-09-03 17:30:18 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , gl_mag_filter_int ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , gl_min_filter_int ) ;
2016-11-03 20:59:11 +00:00
if ( texanis & & ogl_maxanisotropy > 1.0f )
2016-08-29 18:53:10 +00:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , ogl_maxanisotropy ) ;
2011-01-06 11:43:55 +00:00
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGLES // in OpenGL ES 1.1 the mipmaps are automatically generated by a parameter
2016-08-29 18:53:10 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP , buildmipmap ? GL_TRUE : GL_FALSE ) ;
# else
if ( buildmipmap )
2011-01-06 11:43:55 +00:00
{
2007-06-10 16:21:53 +00:00
gluBuild2DMipmaps (
2014-12-02 03:35:01 +00:00
GL_TEXTURE_2D , tex . internalformat ,
2016-08-29 18:53:10 +00:00
tex . tw * rescale , tex . th * rescale , tex . format ,
2007-06-10 16:21:53 +00:00
GL_UNSIGNED_BYTE ,
2014-12-02 03:35:01 +00:00
outP ) ;
2011-01-06 11:43:55 +00:00
}
2006-03-20 16:43:15 +00:00
else
2011-01-06 11:43:55 +00:00
# endif
{
2007-06-10 16:21:53 +00:00
glTexImage2D (
2014-12-02 03:35:01 +00:00
GL_TEXTURE_2D , 0 , tex . internalformat ,
2016-08-29 18:53:10 +00:00
tex . tw * rescale , tex . th * rescale , 0 , tex . format , // RGBA textures.
2006-03-20 16:43:15 +00:00
GL_UNSIGNED_BYTE , // imageData is a GLubyte pointer.
2014-12-02 03:35:01 +00:00
outP ) ;
2011-01-06 11:43:55 +00:00
}
2014-12-02 03:35:01 +00:00
tex_set_size ( tex ) ;
2016-08-29 18:53:10 +00:00
if ( buftemp )
d_free ( buftemp ) ;
2007-06-15 12:32:44 +00:00
r_texcount + + ;
2006-10-20 23:17:48 +00:00
return 0 ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2021-01-17 22:23:23 +00:00
void ogl_loadbmtexture_f ( grs_bitmap & rbm , const opengl_texture_filter texfilt , bool texanis , bool edgepad )
2007-06-10 16:21:53 +00:00
{
2017-01-15 00:03:13 +00:00
assert ( ! rbm . get_flag_mask ( BM_FLAG_PAGED_OUT ) ) ;
2016-10-23 20:33:14 +00:00
assert ( rbm . bm_data ) ;
2014-11-13 03:42:41 +00:00
grs_bitmap * bm = & rbm ;
2018-09-19 02:13:29 +00:00
while ( const auto bm_parent = bm - > bm_parent )
bm = bm_parent ;
2007-06-10 16:21:53 +00:00
if ( bm - > gltexture & & bm - > gltexture - > handle > 0 )
return ;
2014-12-02 03:24:38 +00:00
auto buf = bm - > get_bitmap_data ( ) ;
2017-02-11 21:42:30 +00:00
const unsigned bm_w = bm - > bm_w ;
2007-06-10 16:21:53 +00:00
if ( bm - > gltexture = = NULL ) {
2017-02-11 21:42:30 +00:00
ogl_init_texture ( * ( bm - > gltexture = ogl_get_free_texture ( ) ) , bm_w , bm - > bm_h , ( ( bm - > get_flag_mask ( BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT ) ) ? OGL_FLAG_ALPHA : 0 ) ) ;
2006-03-20 16:43:15 +00:00
}
else {
if ( bm - > gltexture - > handle > 0 )
return ;
if ( bm - > gltexture - > w = = 0 ) {
2017-02-11 21:42:30 +00:00
bm - > gltexture - > lw = bm_w ;
bm - > gltexture - > w = bm_w ;
2006-03-20 16:43:15 +00:00
bm - > gltexture - > h = bm - > bm_h ;
}
}
2007-06-10 16:21:53 +00:00
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , 300 * 1024 > decodebuf ;
2017-01-15 00:03:13 +00:00
if ( bm - > get_flag_mask ( BM_FLAG_RLE ) )
{
2017-02-11 21:42:30 +00:00
class bm_rle_expand_state
{
2018-09-19 02:13:29 +00:00
uint8_t * dbits ;
uint8_t * const ebits ;
2017-02-11 21:42:30 +00:00
public :
2018-09-19 02:13:29 +00:00
bm_rle_expand_state ( uint8_t * const b , uint8_t * const e ) :
dbits ( b ) , ebits ( e )
{
}
2017-02-11 21:42:30 +00:00
uint8_t * get_begin_dbits ( ) const
{
return dbits ;
}
2018-09-19 02:13:29 +00:00
uint8_t * get_end_dbits ( ) const
2017-02-11 21:42:30 +00:00
{
2018-09-19 02:13:29 +00:00
return ebits ;
2017-02-11 21:42:30 +00:00
}
void consume_dbits ( const unsigned w )
{
dbits + = w ;
}
} ;
2018-09-19 02:13:29 +00:00
decodebuf = { } ;
buf = decodebuf . data ( ) ;
if ( ! bm_rle_expand ( * bm ) . loop ( bm_w , bm_rle_expand_state ( begin ( decodebuf ) , end ( decodebuf ) ) ) )
{
2018-10-20 17:25:59 +00:00
con_printf ( CON_URGENT , " error: insufficient space to decode %ux%hu bitmap. Please report this as a bug. " , bm_w , bm - > bm_h ) ;
2018-09-19 02:13:29 +00:00
}
2006-03-20 16:43:15 +00:00
}
2017-01-15 00:03:13 +00:00
ogl_loadtexture ( gr_palette , buf , 0 , 0 , * bm - > gltexture , bm - > get_flags ( ) , 0 , texfilt , texanis , edgepad ) ;
2006-03-20 16:43:15 +00:00
}
2007-06-10 16:21:53 +00:00
2014-11-30 22:09:20 +00:00
static void ogl_freetexture ( ogl_texture & gltexture )
2007-06-10 16:21:53 +00:00
{
2014-11-30 22:09:20 +00:00
if ( gltexture . handle > 0 ) {
2006-03-20 16:43:15 +00:00
r_texcount - - ;
2018-06-08 04:04:05 +00:00
glmprintf ( ( CON_DEBUG , " ogl_freetexture(%p):%i (%i left) " , & gltexture , gltexture . handle , r_texcount ) ) ;
2014-11-30 22:09:20 +00:00
glDeleteTextures ( 1 , & gltexture . handle ) ;
2006-03-20 16:43:15 +00:00
// gltexture->handle=0;
2014-11-30 22:09:20 +00:00
ogl_reset_texture ( gltexture ) ;
2006-03-20 16:43:15 +00:00
}
}
2014-11-30 22:09:20 +00:00
void ogl_freebmtexture ( grs_bitmap & bm )
{
if ( auto & gltexture = bm . gltexture )
2020-05-02 21:18:42 +00:00
ogl_freetexture ( * std : : exchange ( gltexture , nullptr ) ) ;
2006-03-20 16:43:15 +00:00
}
2016-02-12 04:02:28 +00:00
const ogl_colors : : array_type ogl_colors : : white = { {
1.0 , 1.0 , 1.0 , 1.0 ,
1.0 , 1.0 , 1.0 , 1.0 ,
1.0 , 1.0 , 1.0 , 1.0 ,
1.0 , 1.0 , 1.0 , 1.0 ,
} } ;
2018-02-01 05:38:47 +00:00
const ogl_colors : : array_type & ogl_colors : : init_maybe_white ( const int c )
2016-02-12 04:02:28 +00:00
{
return c = = - 1 ? white : init_palette ( c ) ;
}
2018-02-01 05:38:47 +00:00
const ogl_colors : : array_type & ogl_colors : : init_palette ( const unsigned c )
2016-02-12 04:02:28 +00:00
{
const auto & rgb = gr_current_pal [ c ] ;
const GLfloat r = rgb . r / 63.0 , g = rgb . g / 63.0 , b = rgb . b / 63.0 ;
a = { {
r , g , b , 1.0 ,
r , g , b , 1.0 ,
r , g , b , 1.0 ,
r , g , b , 1.0 ,
} } ;
return a ;
}
2016-12-29 03:27:12 +00:00
bool ogl_ubitmapm_cs ( grs_canvas & canvas , int x , int y , int dw , int dh , grs_bitmap & bm , int c , int scale ) // to scale bitmaps
2016-02-12 04:02:28 +00:00
{
ogl_colors color ;
2016-12-29 03:27:12 +00:00
return ogl_ubitmapm_cs ( canvas , x , y , dw , dh , bm , color . init ( c ) , scale ) ;
2016-02-12 04:02:28 +00:00
}
2011-01-06 11:43:55 +00:00
/*
* Menu / gauges
*/
2016-12-29 03:27:12 +00:00
bool ogl_ubitmapm_cs ( grs_canvas & canvas , int x , int y , int dw , int dh , grs_bitmap & bm , const ogl_colors : : array_type & color_array , int scale ) // to scale bitmaps
2006-08-13 15:52:49 +00:00
{
2016-02-12 04:02:28 +00:00
GLfloat yo , xf , yf , u1 , u2 , v1 , v2 , h ;
2016-01-09 16:38:10 +00:00
ogl_client_states < GLfloat , GL_VERTEX_ARRAY , GL_COLOR_ARRAY , GL_TEXTURE_COORD_ARRAY > cs ;
auto & xo = std : : get < 0 > ( cs ) ;
2016-12-29 03:27:12 +00:00
x + = canvas . cv_bitmap . bm_x ;
y + = canvas . cv_bitmap . bm_y ;
2016-06-05 01:04:26 +00:00
xo = x / static_cast < float > ( last_width ) ;
xf = ( bm . bm_w + x ) / static_cast < float > ( last_width ) ;
yo = 1.0 - y / static_cast < float > ( last_height ) ;
yf = 1.0 - ( bm . bm_h + y ) / static_cast < float > ( last_height ) ;
2006-08-13 15:52:49 +00:00
if ( dw < 0 )
2016-12-29 03:27:12 +00:00
dw = canvas . cv_bitmap . bm_w ;
2006-08-13 15:52:49 +00:00
else if ( dw = = 0 )
2014-11-30 22:09:18 +00:00
dw = bm . bm_w ;
2006-08-13 15:52:49 +00:00
if ( dh < 0 )
2016-12-29 03:27:12 +00:00
dh = canvas . cv_bitmap . bm_h ;
2006-08-13 15:52:49 +00:00
else if ( dh = = 0 )
2014-11-30 22:09:18 +00:00
dh = bm . bm_h ;
2006-08-13 15:52:49 +00:00
2016-06-05 01:04:26 +00:00
h = static_cast < double > ( scale ) / static_cast < double > ( F1_0 ) ;
2006-08-13 15:52:49 +00:00
2016-06-05 01:04:26 +00:00
xo = x / ( static_cast < double > ( last_width ) * h ) ;
xf = ( dw + x ) / ( static_cast < double > ( last_width ) * h ) ;
yo = 1.0 - y / ( static_cast < double > ( last_height ) * h ) ;
yf = 1.0 - ( dh + y ) / ( static_cast < double > ( last_height ) * h ) ;
2006-03-20 16:43:15 +00:00
OGL_ENABLE ( TEXTURE_2D ) ;
2016-09-17 13:56:43 +00:00
ogl_bindbmtex ( bm , 0 ) ;
2014-11-30 22:09:18 +00:00
ogl_texwrap ( bm . gltexture , GL_CLAMP_TO_EDGE ) ;
2006-03-20 16:43:15 +00:00
2014-11-30 22:09:18 +00:00
if ( bm . bm_x = = 0 ) {
2006-03-20 16:43:15 +00:00
u1 = 0 ;
2014-11-30 22:09:18 +00:00
if ( bm . bm_w = = bm . gltexture - > w )
u2 = bm . gltexture - > u ;
2006-03-20 16:43:15 +00:00
else
2016-06-05 01:04:26 +00:00
u2 = ( bm . bm_w + bm . bm_x ) / static_cast < float > ( bm . gltexture - > tw ) ;
2006-03-20 16:43:15 +00:00
} else {
2016-06-05 01:04:26 +00:00
u1 = bm . bm_x / static_cast < float > ( bm . gltexture - > tw ) ;
u2 = ( bm . bm_w + bm . bm_x ) / static_cast < float > ( bm . gltexture - > tw ) ;
2006-03-20 16:43:15 +00:00
}
2014-11-30 22:09:18 +00:00
if ( bm . bm_y = = 0 ) {
2006-03-20 16:43:15 +00:00
v1 = 0 ;
2014-11-30 22:09:18 +00:00
if ( bm . bm_h = = bm . gltexture - > h )
v2 = bm . gltexture - > v ;
2006-03-20 16:43:15 +00:00
else
2016-06-05 01:04:26 +00:00
v2 = ( bm . bm_h + bm . bm_y ) / static_cast < float > ( bm . gltexture - > th ) ;
2006-03-20 16:43:15 +00:00
} else {
2016-06-05 01:04:26 +00:00
v1 = bm . bm_y / static_cast < float > ( bm . gltexture - > th ) ;
v2 = ( bm . bm_h + bm . bm_y ) / static_cast < float > ( bm . gltexture - > th ) ;
2006-03-20 16:43:15 +00:00
}
2020-05-02 21:18:42 +00:00
const std : : array < GLfloat , 8 > vertices { {
2016-02-11 03:25:52 +00:00
xo , yo ,
xf , yo ,
xf , yf ,
xo , yf ,
} } ;
2020-05-02 21:18:42 +00:00
const std : : array < GLfloat , 8 > texcoord_array { {
2016-02-11 03:25:52 +00:00
u1 , v1 ,
u2 , v1 ,
u2 , v2 ,
u1 , v2 ,
} } ;
2017-07-08 18:17:49 +00:00
glVertexPointer ( 2 , GL_FLOAT , 0 , vertices . data ( ) ) ;
2016-02-11 03:25:52 +00:00
glColorPointer ( 4 , GL_FLOAT , 0 , color_array . data ( ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , texcoord_array . data ( ) ) ;
2011-01-06 11:43:55 +00:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , 4 ) ; //replaced GL_QUADS
2006-03-20 16:43:15 +00:00
return 0 ;
}
2015-12-13 18:00:48 +00:00
}