Subversion Repositories eduke32

Rev

Rev 8740 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
/**************************************************************************************************
5001 terminx 2
"POLYMOST" code originally written by Ken Silverman
5 Plagman 3
Ken Silverman's official web site: http://www.advsys.net/ken
6658 pogokeen 4
 
5
"POLYMOST2" changes Copyright (c) 2018, Alex Dawson
5 Plagman 6
**************************************************************************************************/
7
 
1173 terminx 8
 
1820 terminx 9
#ifdef USE_OPENGL
1173 terminx 10
 
11
#include "build.h"
7421 terminx 12
#include "common.h"
13
#include "engine_priv.h"
14
#include "kplib.h"
3758 terminx 15
#include "mdsprite.h"
1173 terminx 16
#include "polymost.h"
6883 pogokeen 17
#include "tilepacker.h"
1173 terminx 18
 
19
extern char textfont[2048], smalltextfont[2048];
20
 
1205 terminx 21
int32_t rendmode=0;
4439 terminx 22
int32_t usemodels=1;
23
int32_t usehightile=1;
5 Plagman 24
 
2002 helixhorne 25
typedef struct { float x, cy[2], fy[2]; int32_t tag; int16_t n, p, ctag, ftag; } vsptyp;
6524 terminx 26
#define VSPMAX 2048 //<- careful!
5 Plagman 27
static vsptyp vsp[VSPMAX];
7737 pogokeen 28
static int32_t gtag, viewportNodeCount;
7400 terminx 29
static float xbl, xbr, xbt, xbb;
7379 terminx 30
int32_t domost_rejectcount;
7400 terminx 31
#ifdef YAX_ENABLE
32
typedef struct { float x, cy[2]; int32_t tag; int16_t n, p, ctag; } yax_vsptyp;
33
static yax_vsptyp yax_vsp[YAX_MAXBUNCHES*2][VSPMAX];
34
typedef struct { float x0, x1, cy[2], fy[2]; } yax_hole_t;
35
static yax_hole_t yax_holecf[2][VSPMAX];
36
static int32_t yax_holencf[2];
37
static int32_t yax_drawcf = -1;
38
#endif
5 Plagman 39
 
4605 terminx 40
static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
5 Plagman 41
 
7754 pogokeen 42
//POGOTODO: the SCISDIST could be set to 0 now to allow close objects to render properly,
43
//          but there's a nasty rendering bug that needs to be dug into when setting SCISDIST lower than 1
44
#define SCISDIST 1.f  //close plane clipping distance
5 Plagman 45
 
7412 terminx 46
#define SOFTROTMAT 0
47
 
3403 helixhorne 48
float shadescale = 1.0f;
1848 helixhorne 49
int32_t shadescale_unbounded = 0;
379 terminx 50
 
7681 pogokeen 51
int32_t r_polymostDebug = 0;
6658 pogokeen 52
int32_t r_enablepolymost2 = 0;
6515 hendricks2 53
int32_t r_usenewshading = 4;
8360 hendricks2 54
int32_t r_usetileshades = 1;
7413 terminx 55
int32_t r_npotwallmode = 2;
8441 hendricks2 56
int32_t polymostcenterhoriz = 100;
1943 helixhorne 57
 
4605 terminx 58
static float gviewxrange;
7656 terminx 59
static float ghoriz, ghoriz2;
8441 hendricks2 60
static float ghorizcorrect;
7403 terminx 61
double gxyaspect;
7656 terminx 62
float gyxscale, ghalfx, grhalfxdown10, grhalfxdown10x, ghalfy;
4605 terminx 63
float gcosang, gsinang, gcosang2, gsinang2;
64
float gchang, gshang, gctang, gstang, gvisibility;
65
float gtang = 0.f;
7916 terminx 66
float gvrcorrection = 1.f;
5075 terminx 67
 
7413 terminx 68
static vec3d_t xtex, ytex, otex, xtex2, ytex2, otex2;
5075 terminx 69
 
4667 terminx 70
float fcosglobalang, fsinglobalang;
4768 hendricks2 71
float fxdim, fydim, fydimen, fviewingrange;
1706 helixhorne 72
 
7742 terminx 73
float fsearchx, fsearchy, fsearchz;
74
int psectnum, pwallnum, pbottomwall, pisbottomwall, psearchstat, doeditorcheck = 0;
75
 
5075 terminx 76
static int32_t drawpoly_srepeat = 0, drawpoly_trepeat = 0;
6652 pogokeen 77
#define MAX_DRAWPOLY_VERTS 8
6662 pogokeen 78
#define BUFFER_OFFSET(bytes) (GLintptr) ((GLubyte*) NULL + (bytes))
79
// these cvars are never used directly in rendering -- only when glinit() is called/renderer reset
80
// We do this because we don't want to accidentally overshoot our existing buffer's bounds
81
uint32_t r_persistentStreamBuffer = 1;
82
uint32_t persistentStreamBuffer = r_persistentStreamBuffer;
83
int32_t r_drawpolyVertsBufferLength = 30000;
84
int32_t drawpolyVertsBufferLength = r_drawpolyVertsBufferLength;
85
static GLuint drawpolyVertsID = 0;
86
static GLint drawpolyVertsOffset = 0;
87
static int32_t drawpolyVertsSubBufferIndex = 0;
6883 pogokeen 88
static GLsync drawpolyVertsSync[3] = { 0 };
6662 pogokeen 89
static float defaultDrawpolyVertsArray[MAX_DRAWPOLY_VERTS*5];
90
static float* drawpolyVerts = defaultDrawpolyVertsArray;
590 plagman 91
 
3041 helixhorne 92
struct glfiltermodes glfiltermodes[NUMGLFILTERMODES] =
584 terminx 93
{
94
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
95
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
96
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
97
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
98
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
99
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
100
};
5 Plagman 101
 
5929 terminx 102
int32_t glanisotropy = 0;            // 0 = maximum supported by card
5108 hendricks2 103
int32_t gltexfiltermode = TEXFILTER_OFF;
5001 terminx 104
 
105
#ifdef EDUKE32_GLES
5690 hendricks2 106
int32_t glusetexcompr = 2;
5001 terminx 107
int32_t glusetexcache = 0, glusememcache = 0;
108
#else
1205 terminx 109
int32_t glusetexcompr = 1;
2145 helixhorne 110
int32_t glusetexcache = 2, glusememcache = 1;
5075 terminx 111
int32_t r_polygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
5526 hendricks2 112
static int32_t lastglpolygonmode = 0; //FUK
113
#endif
114
#ifdef USE_GLEXT
5001 terminx 115
int32_t r_detailmapping = 1;
116
int32_t r_glowmapping = 1;
117
#endif
118
 
8711 terminx 119
int polymost2d;
120
 
1205 terminx 121
int32_t gltexmaxsize = 0;      // 0 means autodetection on first run
122
int32_t gltexmiplevel = 0;              // discards this many mipmap levels
7916 terminx 123
int32_t glprojectionhacks = 2;
5 Plagman 124
static GLuint polymosttext = 0;
3784 terminx 125
int32_t glrendmode = REND_POLYMOST;
7650 terminx 126
int32_t r_shadeinterpolate = 1;
228 Plagman 127
 
3146 helixhorne 128
// This variable, and 'shadeforfullbrightpass' control the drawing of
129
// fullbright tiles.  Also see 'fullbrightloadingpass'.
228 Plagman 130
 
5275 terminx 131
int32_t r_fullbrights = 1;
1205 terminx 132
int32_t r_vertexarrays = 1;
5526 hendricks2 133
#ifdef USE_GLEXT
6662 pogokeen 134
//POGOTODO: we no longer support rendering without VBOs -- update any outdated pre-GL2 code that renders without VBOs
1205 terminx 135
int32_t r_vbos = 1;
136
int32_t r_vbocount = 64;
5526 hendricks2 137
#endif
1205 terminx 138
int32_t r_animsmoothing = 1;
3387 helixhorne 139
int32_t r_downsize = 0;
1634 terminx 140
int32_t r_downsizevar = -1;
916 terminx 141
 
7656 terminx 142
int32_t r_yshearing = 0;
8074 terminx 143
int32_t r_flatsky = 1;
7656 terminx 144
 
1329 terminx 145
// used for fogcalc
5079 terminx 146
static float fogresult, fogresult2;
147
coltypef fogcol, fogtable[MAXPALOOKUPS];
5 Plagman 148
 
6776 pogokeen 149
static uint32_t currentShaderProgramID = 0;
6883 pogokeen 150
static GLenum currentActiveTexture = 0;
151
static uint32_t currentTextureID = 0;
6776 pogokeen 152
 
6658 pogokeen 153
static GLuint quadVertsID = 0;
6776 pogokeen 154
static GLuint polymost2BasicShaderProgramID = 0;
6658 pogokeen 155
static GLint texSamplerLoc = -1;
156
static GLint fullBrightSamplerLoc = -1;
157
static GLint projMatrixLoc = -1;
158
static GLint mvMatrixLoc = -1;
159
static GLint texOffsetLoc = -1;
160
static GLint texScaleLoc = -1;
161
static GLint tintLoc = -1;
162
static GLint alphaLoc = -1;
163
static GLint fogRangeLoc = -1;
164
static GLint fogColorLoc = -1;
165
 
6777 pogokeen 166
#define PALSWAP_TEXTURE_SIZE 2048
6776 pogokeen 167
int32_t r_useindexedcolortextures = -1;
6883 pogokeen 168
static GLuint tilesheetTexIDs[MAXTILESHEETS];
169
static GLint tilesheetSize = 0;
170
static vec2f_t tilesheetHalfTexelSize = { 0.f, 0.f };
6776 pogokeen 171
static int32_t lastbasepal = -1;
172
static GLuint paletteTextureIDs[MAXBASEPALS];
6777 pogokeen 173
static GLuint palswapTextureID = 0;
7793 pogokeen 174
extern char const *polymost1Frag;
175
extern char const *polymost1Vert;
6776 pogokeen 176
static GLuint polymost1CurrentShaderProgramID = 0;
177
static GLuint polymost1BasicShaderProgramID = 0;
178
static GLuint polymost1ExtendedShaderProgramID = 0;
179
static GLint polymost1TexSamplerLoc = -1;
180
static GLint polymost1PalSwapSamplerLoc = -1;
181
static GLint polymost1PaletteSamplerLoc = -1;
182
static GLint polymost1DetailSamplerLoc = -1;
183
static GLint polymost1GlowSamplerLoc = -1;
6883 pogokeen 184
static GLint polymost1TexturePosSizeLoc = -1;
185
static vec4f_t polymost1TexturePosSize = { 0.f, 0.f, 1.f, 1.f };
186
static GLint polymost1HalfTexelSizeLoc = -1;
187
static vec2f_t polymost1HalfTexelSize = { 0.f, 0.f };
6777 pogokeen 188
static GLint polymost1PalswapPosLoc = -1;
6883 pogokeen 189
static vec2f_t polymost1PalswapPos = { 0.f, 0.f };
6777 pogokeen 190
static GLint polymost1PalswapSizeLoc = -1;
6883 pogokeen 191
static vec2f_t polymost1PalswapSize = { 0.f, 0.f };
192
static vec2f_t polymost1PalswapInnerSize = { 0.f, 0.f };
7783 pogokeen 193
static GLint polymost1ClampLoc = -1;
8074 terminx 194
static vec2f_t polymost1Clamp = { 0.f, 0.f };
6776 pogokeen 195
static GLint polymost1ShadeLoc = -1;
196
static float polymost1Shade = 0.f;
7412 terminx 197
static GLint polymost1NumShadesLoc = -1;
198
static float polymost1NumShades = 64.f;
199
static GLint polymost1VisFactorLoc = -1;
200
static float polymost1VisFactor = 128.f;
6776 pogokeen 201
static GLint polymost1FogEnabledLoc = -1;
202
static float polymost1FogEnabled = 1.f;
203
static GLint polymost1UseColorOnlyLoc = -1;
204
static float polymost1UseColorOnly = 0.f;
205
static GLint polymost1UsePaletteLoc = -1;
206
static float polymost1UsePalette = 1.f;
207
static GLint polymost1UseDetailMappingLoc = -1;
208
static float polymost1UseDetailMapping = 0.f;
209
static GLint polymost1UseGlowMappingLoc = -1;
210
static float polymost1UseGlowMapping = 0.f;
7413 terminx 211
static GLint polymost1NPOTEmulationLoc = -1;
212
static float polymost1NPOTEmulation = 0.f;
213
static GLint polymost1NPOTEmulationFactorLoc = -1;
214
static float polymost1NPOTEmulationFactor = 1.f;
215
static GLint polymost1NPOTEmulationXOffsetLoc = -1;
216
static float polymost1NPOTEmulationXOffset = 0.f;
7412 terminx 217
static GLint polymost1RotMatrixLoc = -1;
218
static float polymost1RotMatrix[16] = { 1.f, 0.f, 0.f, 0.f,
219
                                        0.f, 1.f, 0.f, 0.f,
220
                                        0.f, 0.f, 1.f, 0.f,
221
                                        0.f, 0.f, 0.f, 1.f };
7650 terminx 222
static GLint polymost1ShadeInterpolateLoc = -1;
223
static float polymost1ShadeInterpolate = 1.f;
6776 pogokeen 224
 
6175 terminx 225
static inline float float_trans(uint32_t maskprops, uint8_t blend)
5888 hendricks2 226
{
227
    switch (maskprops)
228
    {
229
    case DAMETH_TRANS1:
230
    case DAMETH_TRANS2:
231
        return glblend[blend].def[maskprops-2].alpha;
232
    default:
233
        return 1.0f;
234
    }
235
}
4623 terminx 236
 
3758 terminx 237
char ptempbuf[MAXWALLSB<<1];
1173 terminx 238
 
1064 terminx 239
// polymost ART sky control
1205 terminx 240
int32_t r_parallaxskyclamping = 1;
6521 hendricks2 241
int32_t r_parallaxskypanning = 1;
1064 terminx 242
 
2045 helixhorne 243
#define MIN_CACHETIME_PRINT 10
1784 helixhorne 244
 
4675 terminx 245
// this was faster in MSVC but slower with GCC... currently unknown on ARM where both
246
// the FPU and possibly the optimization path in the compiler need improvement
247
#if 0
5158 helixhorne 248
static inline int32_t __float_as_int(float f) { return *(int32_t *) &f; }
4675 terminx 249
static inline float __int_as_float(int32_t d) { return *(float *) &d; }
250
static inline float Bfabsf(float f) { return __int_as_float(__float_as_int(f)&0x7fffffff); }
251
#else
252
#define Bfabsf fabsf
253
#endif
254
 
1652 terminx 255
int32_t mdtims, omdtims;
5075 terminx 256
uint8_t alphahackarray[MAXTILES];
1205 terminx 257
int32_t drawingskybox = 0;
3758 terminx 258
int32_t hicprecaching = 0;
5 Plagman 259
 
5277 terminx 260
hitdata_t polymost_hitdata;
261
 
7681 pogokeen 262
void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...)
263
{
264
    static char msg[8192];
265
    va_list vArgs;
266
 
267
    if (!glinfo.debugoutput ||
268
        r_polymostDebug < severity)
269
    {
270
        return;
271
    }
272
 
273
    va_start(vArgs, format);
274
    Bvsnprintf(msg, sizeof(msg), format, vArgs);
275
    va_end(vArgs);
276
 
277
    glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB,
278
                            GL_DEBUG_TYPE_OTHER_ARB,
279
                            0,
280
                            GL_DEBUG_SEVERITY_HIGH_ARB+severity-1,
281
                            -1,
282
                            msg);
283
}
284
 
4690 terminx 285
#if 0
1221 terminx 286
static inline int32_t gltexmayhavealpha(int32_t dapicnum, int32_t dapalnum)
5 Plagman 287
{
3146 helixhorne 288
    const int32_t j = (dapicnum&(GLTEXCACHEADSIZ-1));
109 terminx 289
    pthtyp *pth;
5 Plagman 290
 
3781 terminx 291
    for (pth=texcache.list[j]; pth; pth=pth->next)
3146 helixhorne 292
        if (pth->picnum == dapicnum && pth->palnum == dapalnum)
4486 helixhorne 293
            return ((pth->flags&PTH_HASALPHA) != 0);
3146 helixhorne 294
 
295
    return 1;
5 Plagman 296
}
4690 terminx 297
#endif
5 Plagman 298
 
1205 terminx 299
void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth)
5 Plagman 300
{
5075 terminx 301
    const int32_t pic = (dapicnum&(GLTEXCACHEADSIZ-1));
5 Plagman 302
 
5075 terminx 303
    for (pthtyp *pth=texcache.list[pic]; pth; pth=pth->next)
4486 helixhorne 304
        if (pth->picnum == dapicnum && pth->palnum == dapalnum &&
305
            (pth->flags & PTH_CLAMPED) == TO_PTH_CLAMPED(dameth))
248 terminx 306
        {
4486 helixhorne 307
            pth->flags |= PTH_INVALIDATED;
308
            if (pth->flags & PTH_HASFULLBRIGHT)
309
                pth->ofb->flags |= PTH_INVALIDATED;
248 terminx 310
        }
5 Plagman 311
}
312
 
109 terminx 313
//Make all textures "dirty" so they reload, but not re-allocate
314
//This should be much faster than polymost_glreset()
315
//Use this for palette effects ... but not ones that change every frame!
3765 terminx 316
void gltexinvalidatetype(int32_t type)
5 Plagman 317
{
5829 terminx 318
    for (bssize_t j=0; j<=GLTEXCACHEADSIZ-1; j++)
3758 terminx 319
    {
5075 terminx 320
        for (pthtyp *pth=texcache.list[j]; pth; pth=pth->next)
248 terminx 321
        {
6776 pogokeen 322
            if (type == INVALIDATE_ALL ||
323
                (type == INVALIDATE_ALL_NON_INDEXED && !(pth->flags & PTH_INDEXED)) ||
324
                (type == INVALIDATE_ART && pth->hicr == NULL) ||
325
                (type == INVALIDATE_ART_NON_INDEXED && pth->hicr == NULL && !(pth->flags & PTH_INDEXED)))
415 terminx 326
            {
4486 helixhorne 327
                pth->flags |= PTH_INVALIDATED;
328
                if (pth->flags & PTH_HASFULLBRIGHT)
329
                    pth->ofb->flags |= PTH_INVALIDATED;
415 terminx 330
            }
331
        }
3758 terminx 332
    }
333
 
5494 hendricks2 334
    clearskins(type);
335
 
415 terminx 336
#ifdef DEBUGGINGAIDS
3758 terminx 337
    OSD_Printf("gltexinvalidateall()\n");
415 terminx 338
#endif
339
}
340
 
5001 terminx 341
static void bind_2d_texture(GLuint texture, int filter)
3041 helixhorne 342
{
5001 terminx 343
    if (filter == -1)
344
        filter = gltexfiltermode;
345
 
6656 pogokeen 346
    glBindTexture(GL_TEXTURE_2D, texture);
347
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
348
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
5526 hendricks2 349
#ifdef USE_GLEXT
4605 terminx 350
    if (glinfo.maxanisotropy > 1.f)
6656 pogokeen 351
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
5001 terminx 352
#endif
3041 helixhorne 353
}
354
 
584 terminx 355
void gltexapplyprops(void)
5 Plagman 356
{
6829 terminx 357
    if (videoGetRenderMode() == REND_CLASSIC)
3628 helixhorne 358
        return;
359
 
4605 terminx 360
    if (glinfo.maxanisotropy > 1.f)
109 terminx 361
    {
3041 helixhorne 362
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)
363
            glanisotropy = (int32_t)glinfo.maxanisotropy;
109 terminx 364
    }
5 Plagman 365
 
3041 helixhorne 366
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
6776 pogokeen 367
    r_useindexedcolortextures = !gltexfiltermode;
3041 helixhorne 368
 
5829 terminx 369
    for (bssize_t i=0; i<=GLTEXCACHEADSIZ-1; i++)
584 terminx 370
    {
5075 terminx 371
        for (pthtyp *pth=texcache.list[i]; pth; pth=pth->next)
584 terminx 372
        {
6776 pogokeen 373
            if (pth->flags & PTH_INDEXED)
374
            {
375
                //POGO: indexed textures should not be filtered
376
                continue;
377
            }
378
 
7109 terminx 379
            int32_t const filter = (pth->flags & PTH_FORCEFILTER) ? TEXFILTER_ON : -1;
3041 helixhorne 380
 
5108 hendricks2 381
            bind_2d_texture(pth->glpic, filter);
5001 terminx 382
 
383
            if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT)
5108 hendricks2 384
                bind_2d_texture(pth->ofb->glpic, filter);
109 terminx 385
        }
386
    }
5 Plagman 387
 
5829 terminx 388
    for (bssize_t i=0; i<nextmodelid; i++)
5075 terminx 389
    {
390
        md2model_t *m = (md2model_t *)models[i];
5001 terminx 391
 
5075 terminx 392
        if (m->mdnum < 2)
393
            continue;
394
 
6214 hendricks2 395
        for (bssize_t j = 0; j < m->numskins * HICTINT_MEMORY_COMBINATIONS; j++)
5001 terminx 396
        {
5075 terminx 397
            if (!m->texid[j])
398
                continue;
5001 terminx 399
            bind_2d_texture(m->texid[j], -1);
400
        }
109 terminx 401
 
5075 terminx 402
        for (mdskinmap_t *sk = m->skinmap; sk; sk = sk->next)
6214 hendricks2 403
            for (bssize_t j = 0; j < HICTINT_MEMORY_COMBINATIONS; j++)
109 terminx 404
            {
5075 terminx 405
                if (!sk->texid[j])
406
                    continue;
7109 terminx 407
                bind_2d_texture(sk->texid[j], (sk->flags & HICR_FORCEFILTER) ? TEXFILTER_ON : -1);
109 terminx 408
            }
409
    }
5 Plagman 410
}
411
 
412
//--------------------------------------------------------------------------------------------------
3758 terminx 413
 
109 terminx 414
//Use this for both initialization and uninitialization of OpenGL.
1205 terminx 415
static int32_t gltexcacnum = -1;
1652 terminx 416
 
6658 pogokeen 417
//in-place multiply m0=m0*m1
7916 terminx 418
float* multiplyMatrix4f(float m0[4*4], const float m1[4*4])
6658 pogokeen 419
{
420
    float mR[4*4];
6700 hendricks2 421
 
6658 pogokeen 422
#define multMatrix4RowCol(r, c) mR[r*4+c] = m0[r*4]*m1[c] + m0[r*4+1]*m1[c+4] + m0[r*4+2]*m1[c+8] + m0[r*4+3]*m1[c+12]
6700 hendricks2 423
 
6658 pogokeen 424
    multMatrix4RowCol(0, 0);
425
    multMatrix4RowCol(0, 1);
426
    multMatrix4RowCol(0, 2);
427
    multMatrix4RowCol(0, 3);
6700 hendricks2 428
 
6658 pogokeen 429
    multMatrix4RowCol(1, 0);
430
    multMatrix4RowCol(1, 1);
431
    multMatrix4RowCol(1, 2);
432
    multMatrix4RowCol(1, 3);
6700 hendricks2 433
 
6658 pogokeen 434
    multMatrix4RowCol(2, 0);
435
    multMatrix4RowCol(2, 1);
436
    multMatrix4RowCol(2, 2);
437
    multMatrix4RowCol(2, 3);
6700 hendricks2 438
 
6658 pogokeen 439
    multMatrix4RowCol(3, 0);
440
    multMatrix4RowCol(3, 1);
441
    multMatrix4RowCol(3, 2);
442
    multMatrix4RowCol(3, 3);
6700 hendricks2 443
 
6658 pogokeen 444
    Bmemcpy(m0, mR, sizeof(float)*4*4);
6700 hendricks2 445
 
6658 pogokeen 446
    return m0;
6700 hendricks2 447
 
6658 pogokeen 448
#undef multMatrix4RowCol
449
}
450
 
451
static void calcmat(vec3f_t a0, const vec2f_t *offset, float f, float mat[16], int16_t angle)
452
{
453
    float g;
454
    float k0, k1, k2, k3, k4, k5, k6, k7;
455
 
456
    k0 = a0.y;
457
    k1 = a0.x;
458
    a0.x += offset->x;
459
    a0.z += offset->y;
460
    f = gcosang2*gshang;
461
    g = gsinang2*gshang;
462
    k4 = (float)sintable[(angle+1024)&2047] * (1.f/16384.f);
463
    k5 = (float)sintable[(angle+512)&2047] * (1.f/16384.f);
464
    k2 = k0*(1-k4)+k1*k5;
465
    k3 = k1*(1-k4)-k0*k5;
466
    k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
467
    mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
468
    k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
469
    mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
470
    k6 =           gcosang2*gchang; k7 =           gsinang2*gchang;
471
    mat[2] = k4*k6 + k5*k7; mat[6] =-gshang;        mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
472
 
473
    mat[12] = (mat[12] + a0.y*mat[0]) + (a0.z*mat[4] + a0.x*mat[ 8]);
474
    mat[13] = (mat[13] + a0.y*mat[1]) + (a0.z*mat[5] + a0.x*mat[ 9]);
475
    mat[14] = (mat[14] + a0.y*mat[2]) + (a0.z*mat[6] + a0.x*mat[10]);
476
}
477
 
7787 hendricks2 478
static GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int * pLength = nullptr)
6658 pogokeen 479
{
480
    GLuint shaderID = glCreateShader(shaderType);
481
    if (shaderID == 0)
482
    {
483
        return 0;
484
    }
6700 hendricks2 485
 
6658 pogokeen 486
    glShaderSource(shaderID,
487
                   1,
7782 pogokeen 488
                   &source,
7787 hendricks2 489
                   pLength);
6658 pogokeen 490
    glCompileShader(shaderID);
6700 hendricks2 491
 
6671 pogokeen 492
    GLint compileStatus;
493
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
494
    if (!compileStatus)
6658 pogokeen 495
    {
6671 pogokeen 496
        GLint logLength;
497
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
6960 pogokeen 498
        OSD_Printf("Compile Status: %u\n", compileStatus);
6671 pogokeen 499
        if (logLength > 0)
500
        {
7079 terminx 501
            char *infoLog = (char*)Xmalloc(logLength);
6671 pogokeen 502
            glGetShaderInfoLog(shaderID, logLength, &logLength, infoLog);
503
            OSD_Printf("Log:\n%s\n", infoLog);
504
            free(infoLog);
505
        }
6658 pogokeen 506
    }
6700 hendricks2 507
 
6658 pogokeen 508
    return shaderID;
509
}
510
 
7787 hendricks2 511
static GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int length)
512
{
513
    return polymost2_compileShader(shaderType, source, &length);
514
}
515
 
584 terminx 516
void polymost_glreset()
5 Plagman 517
{
5829 terminx 518
    for (bssize_t i=0; i<=MAXPALOOKUPS-1; i++)
1220 terminx 519
    {
5349 hendricks2 520
        fogtable[i].r = palookupfog[i].r * (1.f/255.f);
521
        fogtable[i].g = palookupfog[i].g * (1.f/255.f);
522
        fogtable[i].b = palookupfog[i].b * (1.f/255.f);
5079 terminx 523
        fogtable[i].a = 0;
1220 terminx 524
    }
525
 
109 terminx 526
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
527
    if (gltexcacnum < 0)
528
    {
529
        gltexcacnum = 0;
5 Plagman 530
 
109 terminx 531
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
4605 terminx 532
        gcosang = gcosang2 = 16384.f/262144.f;
5079 terminx 533
        gsinang = gsinang2 = 0.f;
109 terminx 534
    }
535
    else
536
    {
5829 terminx 537
        for (bssize_t i = 0; i <= GLTEXCACHEADSIZ-1; i++)
584 terminx 538
        {
5075 terminx 539
            for (pthtyp *pth = texcache.list[i]; pth;)
584 terminx 540
            {
5075 terminx 541
                pthtyp *const next = pth->next;
542
 
4486 helixhorne 543
                if (pth->flags & PTH_HASFULLBRIGHT)
248 terminx 544
                {
6656 pogokeen 545
                    glDeleteTextures(1, &pth->ofb->glpic);
7705 terminx 546
                    Xfree(pth->ofb);
248 terminx 547
                }
2639 helixhorne 548
 
6656 pogokeen 549
                glDeleteTextures(1, &pth->glpic);
7705 terminx 550
                Xfree(pth);
109 terminx 551
                pth = next;
552
            }
2639 helixhorne 553
 
3781 terminx 554
            texcache.list[i] = NULL;
109 terminx 555
        }
5075 terminx 556
 
5494 hendricks2 557
        clearskins(INVALIDATE_ALL);
109 terminx 558
    }
559
 
2639 helixhorne 560
    if (polymosttext)
6656 pogokeen 561
        glDeleteTextures(1,&polymosttext);
109 terminx 562
    polymosttext=0;
563
 
5526 hendricks2 564
#ifdef USE_GLEXT
4639 terminx 565
    md_freevbos();
5526 hendricks2 566
#endif
1317 terminx 567
 
4675 terminx 568
    Bmemset(texcache.list,0,sizeof(texcache.list));
446 Plagman 569
 
3758 terminx 570
    texcache_freeptrs();
5001 terminx 571
    texcache_syncmemcache();
1155 terminx 572
 
2014 helixhorne 573
#ifdef DEBUGGINGAIDS
574
    OSD_Printf("polymost_glreset()\n");
575
#endif
5 Plagman 576
}
577
 
5715 hendricks2 578
#if defined EDUKE32_GLES
579
static void Polymost_DetermineTextureFormatSupport(void);
580
#endif
2240 helixhorne 581
 
6652 pogokeen 582
// reset vertex pointers to polymost default
583
void polymost_resetVertexPointers()
584
{
7681 pogokeen 585
    polymost_outputGLDebugMessage(3, "polymost_resetVertexPointers()");
586
 
6662 pogokeen 587
    glBindBuffer(GL_ARRAY_BUFFER, drawpolyVertsID);
6700 hendricks2 588
 
6662 pogokeen 589
    glVertexPointer(3, GL_FLOAT, 5*sizeof(float), 0);
590
    glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6700 hendricks2 591
 
6652 pogokeen 592
#ifdef USE_GLEXT
593
    if (r_detailmapping)
594
    {
6776 pogokeen 595
        glClientActiveTexture(GL_TEXTURE3);
6662 pogokeen 596
        glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6652 pogokeen 597
    }
598
    if (r_glowmapping)
599
    {
6776 pogokeen 600
        glClientActiveTexture(GL_TEXTURE4);
6662 pogokeen 601
        glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), (GLvoid*) (3*sizeof(float)));
6652 pogokeen 602
    }
6656 pogokeen 603
    glClientActiveTexture(GL_TEXTURE0);
6652 pogokeen 604
#endif
6776 pogokeen 605
 
606
    polymost_resetProgram();
6652 pogokeen 607
}
608
 
6776 pogokeen 609
void polymost_disableProgram()
610
{
7419 terminx 611
    if (videoGetRenderMode() != REND_POLYMOST)
612
        return;
613
 
7681 pogokeen 614
    polymost_outputGLDebugMessage(3, "polymost_disableProgram()");
615
 
8713 terminx 616
    polymost_useShaderProgram(0);
6776 pogokeen 617
}
618
 
619
void polymost_resetProgram()
620
{
7419 terminx 621
    if (videoGetRenderMode() != REND_POLYMOST)
622
        return;
6777 pogokeen 623
 
7681 pogokeen 624
    polymost_outputGLDebugMessage(3, "polymost_resetProgram()");
625
 
7419 terminx 626
    if (r_enablepolymost2)
8713 terminx 627
        polymost_useShaderProgram(polymost2BasicShaderProgramID);
7419 terminx 628
    else
8713 terminx 629
        polymost_useShaderProgram(polymost1CurrentShaderProgramID);
7419 terminx 630
 
631
    // ensure that palswapTexture and paletteTexture[curbasepal] is bound
632
    glActiveTexture(GL_TEXTURE1);
633
    glBindTexture(GL_TEXTURE_2D, palswapTextureID);
634
    glActiveTexture(GL_TEXTURE2);
635
    glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[curbasepal]);
636
    glActiveTexture(GL_TEXTURE0);
6776 pogokeen 637
}
638
 
639
static void polymost_setCurrentShaderProgram(uint32_t programID)
640
{
7681 pogokeen 641
    polymost_outputGLDebugMessage(3, "polymost_setCurrentShaderProgram(programID:%u)", programID);
642
 
6776 pogokeen 643
    polymost1CurrentShaderProgramID = programID;
8713 terminx 644
    polymost_useShaderProgram(programID);
6776 pogokeen 645
 
646
    //update the uniform locations
647
    polymost1TexSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_texture");
648
    polymost1PalSwapSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palswap");
649
    polymost1PaletteSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palette");
650
    polymost1DetailSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_detail");
651
    polymost1GlowSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_glow");
6883 pogokeen 652
    polymost1TexturePosSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_texturePosSize");
653
    polymost1HalfTexelSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_halfTexelSize");
6777 pogokeen 654
    polymost1PalswapPosLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapPos");
655
    polymost1PalswapSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapSize");
7783 pogokeen 656
    polymost1ClampLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_clamp");
6776 pogokeen 657
    polymost1ShadeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_shade");
7412 terminx 658
    polymost1NumShadesLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_numShades");
659
    polymost1VisFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_visFactor");
6776 pogokeen 660
    polymost1FogEnabledLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_fogEnabled");
661
    polymost1UsePaletteLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_usePalette");
662
    polymost1UseColorOnlyLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useColorOnly");
663
    polymost1UseDetailMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useDetailMapping");
664
    polymost1UseGlowMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useGlowMapping");
7413 terminx 665
    polymost1NPOTEmulationLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulation");
666
    polymost1NPOTEmulationFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationFactor");
667
    polymost1NPOTEmulationXOffsetLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationXOffset");
7412 terminx 668
    polymost1RotMatrixLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_rotMatrix");
7650 terminx 669
    polymost1ShadeInterpolateLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_shadeInterpolate");
6776 pogokeen 670
 
671
    //set the uniforms to the current values
6883 pogokeen 672
    glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
673
    glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
6777 pogokeen 674
    glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
675
    glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
8074 terminx 676
    glUniform2f(polymost1ClampLoc, polymost1Clamp.x, polymost1Clamp.y);
6776 pogokeen 677
    glUniform1f(polymost1ShadeLoc, polymost1Shade);
7412 terminx 678
    glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
679
    glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
6776 pogokeen 680
    glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
681
    glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
682
    glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
683
    glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
684
    glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
7413 terminx 685
    glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
686
    glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
687
    glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
7412 terminx 688
    glUniformMatrix4fv(polymost1RotMatrixLoc, 1, false, polymost1RotMatrix);
7650 terminx 689
    glUniform1f(polymost1ShadeInterpolateLoc, polymost1ShadeInterpolate);
6776 pogokeen 690
}
691
 
7085 terminx 692
void polymost_setTexturePosSize(vec4f_t const &texturePosSize)
6883 pogokeen 693
{
7419 terminx 694
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
695
        return;
696
 
697
    polymost1TexturePosSize = texturePosSize;
698
    glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
6883 pogokeen 699
}
700
 
7458 terminx 701
void polymost_setHalfTexelSize(vec2f_t const &halfTexelSize)
6883 pogokeen 702
{
7419 terminx 703
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || (halfTexelSize.x == polymost1HalfTexelSize.x && halfTexelSize.y == polymost1HalfTexelSize.y))
704
        return;
705
 
706
    polymost1HalfTexelSize = halfTexelSize;
707
    glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
6883 pogokeen 708
}
709
 
6777 pogokeen 710
static void polymost_setPalswap(uint32_t index)
711
{
7419 terminx 712
    static uint32_t lastPalswapIndex;
6777 pogokeen 713
 
7419 terminx 714
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || index == lastPalswapIndex)
715
        return;
716
 
717
    lastPalswapIndex = index;
718
    polymost1PalswapPos.x = index*polymost1PalswapSize.x;
719
    polymost1PalswapPos.y = floorf(polymost1PalswapPos.x);
7434 terminx 720
    polymost1PalswapPos = { polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f/PALSWAP_TEXTURE_SIZE),
721
                            polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f/PALSWAP_TEXTURE_SIZE) };
7419 terminx 722
    glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
6777 pogokeen 723
}
724
 
725
static void polymost_setPalswapSize(uint32_t width, uint32_t height)
726
{
7419 terminx 727
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
728
        return;
729
 
7434 terminx 730
    polymost1PalswapSize = { width*(1.f/PALSWAP_TEXTURE_SIZE),
731
                             height*(1.f/PALSWAP_TEXTURE_SIZE) };
732
 
733
    polymost1PalswapInnerSize = { (width-1)*(1.f/PALSWAP_TEXTURE_SIZE),
734
                                  (height-1)*(1.f/PALSWAP_TEXTURE_SIZE) };
735
 
7419 terminx 736
    glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
6777 pogokeen 737
}
738
 
7783 pogokeen 739
char polymost_getClamp()
740
{
8074 terminx 741
    return polymost1Clamp.x + polymost1Clamp.y*2.0;
7783 pogokeen 742
}
743
 
744
void polymost_setClamp(char clamp)
745
{
8074 terminx 746
    char clampx = clamp&1;
747
    char clampy = clamp>>1;
7783 pogokeen 748
    if (currentShaderProgramID != polymost1CurrentShaderProgramID ||
8074 terminx 749
        (clampx == polymost1Clamp.x && clampy == polymost1Clamp.y))
7783 pogokeen 750
        return;
751
 
8074 terminx 752
    polymost1Clamp.x = clampx;
753
    polymost1Clamp.y = clampy;
754
    glUniform2f(polymost1ClampLoc, polymost1Clamp.x, polymost1Clamp.y);
7783 pogokeen 755
}
756
 
6777 pogokeen 757
static void polymost_setShade(int32_t shade)
758
{
7419 terminx 759
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
760
        return;
761
 
8359 hendricks2 762
    if (!polymost_usetileshades())
7419 terminx 763
        shade = 0;
764
 
765
    static int32_t lastShade;
766
    static int32_t lastNumShades;
767
 
768
    if (shade != lastShade)
6777 pogokeen 769
    {
7419 terminx 770
        lastShade = shade;
771
        polymost1Shade = shade;
772
        glUniform1f(polymost1ShadeLoc, polymost1Shade);
773
    }
6936 pogokeen 774
 
7419 terminx 775
    if (numshades != lastNumShades)
776
    {
777
        lastNumShades = numshades;
778
        polymost1NumShades = numshades;
779
        glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
7412 terminx 780
    }
781
}
6777 pogokeen 782
 
7458 terminx 783
void polymost_setVisibility(float visibility)
7412 terminx 784
{
7419 terminx 785
    if (currentShaderProgramID != polymost1CurrentShaderProgramID)
786
        return;
787
 
8359 hendricks2 788
    if (!polymost_usetileshades())
8357 hendricks2 789
        visibility = -16;
790
 
7737 pogokeen 791
    float visFactor = visibility * fviewingrange * (1.f / (64.f * 65536.f));
792
    if (visFactor == polymost1VisFactor)
793
        return;
794
 
795
    polymost1VisFactor = visFactor;
7419 terminx 796
    glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
6777 pogokeen 797
}
798
 
6776 pogokeen 799
void polymost_setFogEnabled(char fogEnabled)
800
{
7419 terminx 801
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || fogEnabled == polymost1FogEnabled)
802
        return;
803
 
804
    polymost1FogEnabled = fogEnabled;
805
    glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
6776 pogokeen 806
}
807
 
808
void polymost_useColorOnly(char useColorOnly)
809
{
7419 terminx 810
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useColorOnly == polymost1UseColorOnly)
811
        return;
812
 
813
    polymost1UseColorOnly = useColorOnly;
814
    glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
6776 pogokeen 815
}
816
 
817
void polymost_usePaletteIndexing(char usePaletteIndexing)
818
{
7419 terminx 819
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || usePaletteIndexing == polymost1UsePalette)
820
        return;
821
 
822
    polymost1UsePalette = usePaletteIndexing;
823
    glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
6776 pogokeen 824
}
825
 
826
void polymost_useDetailMapping(char useDetailMapping)
827
{
7419 terminx 828
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useDetailMapping == polymost1UseDetailMapping)
829
        return;
6777 pogokeen 830
 
7419 terminx 831
    if (useDetailMapping)
832
        polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
6776 pogokeen 833
 
7419 terminx 834
    polymost1UseDetailMapping = useDetailMapping;
835
    glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
6776 pogokeen 836
}
837
 
838
void polymost_useGlowMapping(char useGlowMapping)
839
{
7419 terminx 840
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || useGlowMapping == polymost1UseGlowMapping)
841
        return;
6777 pogokeen 842
 
7419 terminx 843
    if (useGlowMapping)
844
        polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
6776 pogokeen 845
 
7419 terminx 846
    polymost1UseGlowMapping = useGlowMapping;
847
    glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
6776 pogokeen 848
}
849
 
7413 terminx 850
void polymost_npotEmulation(char npotEmulation, float factor, float xOffset)
851
{
7419 terminx 852
    if (currentShaderProgramID != polymost1CurrentShaderProgramID || npotEmulation == polymost1NPOTEmulation)
853
        return;
854
 
855
    polymost1NPOTEmulation = npotEmulation;
856
    glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
857
    polymost1NPOTEmulationFactor = factor;
858
    glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
859
    polymost1NPOTEmulationXOffset = xOffset;
860
    glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
7413 terminx 861
}
862
 
7650 terminx 863
void polymost_shadeInterpolate(int32_t shadeInterpolate)
864
{
865
    if (currentShaderProgramID == polymost1CurrentShaderProgramID)
866
    {
867
        polymost1ShadeInterpolate = shadeInterpolate;
868
        glUniform1f(polymost1ShadeInterpolateLoc, polymost1ShadeInterpolate);
869
    }
870
}
871
 
6883 pogokeen 872
void polymost_activeTexture(GLenum texture)
873
{
874
    currentActiveTexture = texture;
8739 hendricks2 875
    glad_glActiveTexture(texture);
6883 pogokeen 876
}
877
 
878
//POGOTODO: replace this and polymost_activeTexture with proper draw call organization
879
void polymost_bindTexture(GLenum target, uint32_t textureID)
880
{
881
    if (currentTextureID != textureID ||
882
        textureID == 0 ||
883
        currentActiveTexture != GL_TEXTURE0 ||
884
        videoGetRenderMode() != REND_POLYMOST)
885
    {
886
        glad_glBindTexture(target, textureID);
887
        if (currentActiveTexture == GL_TEXTURE0)
888
        {
889
            currentTextureID = textureID;
890
        }
891
    }
892
}
893
 
7109 terminx 894
static void polymost_bindPth(pthtyp const * const pPth)
6883 pogokeen 895
{
7041 terminx 896
    Bassert(pPth);
897
 
6883 pogokeen 898
    vec4f_t texturePosSize = { 0.f, 0.f, 1.f, 1.f };
899
    vec2f_t halfTexelSize = { 0.f, 0.f };
6885 pogokeen 900
    if ((pPth->flags & PTH_INDEXED) &&
6883 pogokeen 901
        !(pPth->flags & PTH_HIGHTILE))
902
    {
903
        Tile tile;
904
        char tileIsPacked = tilepacker_getTile(waloff[pPth->picnum] ? pPth->picnum+1 : 0, &tile);
905
        //POGO: check the width and height to ensure that the tile hasn't been changed for a user tile that has different dimensions
906
        if (tileIsPacked &&
907
            (!waloff[pPth->picnum] ||
7887 pogokeen 908
             (tile.rect.width >= (uint32_t) tilesiz[pPth->picnum].y &&
909
              tile.rect.height >= (uint32_t) tilesiz[pPth->picnum].x)))
6883 pogokeen 910
        {
911
            texturePosSize = { tile.rect.u/(float) tilesheetSize,
912
                               tile.rect.v/(float) tilesheetSize,
7887 pogokeen 913
                               tilesiz[pPth->picnum].y/(float) tilesheetSize,
914
                               tilesiz[pPth->picnum].x/(float) tilesheetSize };
6883 pogokeen 915
            halfTexelSize = tilesheetHalfTexelSize;
916
        }
917
    }
918
    polymost_setTexturePosSize(texturePosSize);
919
    polymost_setHalfTexelSize(halfTexelSize);
920
    glBindTexture(GL_TEXTURE_2D, pPth->glpic);
921
}
922
 
8713 terminx 923
void polymost_useShaderProgram(uint32_t shaderID)
6776 pogokeen 924
{
8739 hendricks2 925
    glUseProgram(shaderID);
6776 pogokeen 926
    currentShaderProgramID = shaderID;
927
}
928
 
627 terminx 929
// one-time initialization of OpenGL for polymost
5 Plagman 930
void polymost_glinit()
931
{
6656 pogokeen 932
    glHint(GL_FOG_HINT, GL_NICEST);
933
    glFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR);
934
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
109 terminx 935
 
6656 pogokeen 936
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
937
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2579 plagman 938
 
7754 pogokeen 939
    if (glinfo.depthclamp)
940
        glEnable(GL_DEPTH_CLAMP);
941
 
6656 pogokeen 942
    //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
943
    //glEnable(GL_LINE_SMOOTH);
6700 hendricks2 944
 
6776 pogokeen 945
    if (r_useindexedcolortextures == -1)
946
    {
947
        //POGO: r_useindexedcolortextures has never been set, so force it to be enabled
948
        gltexfiltermode = 0;
949
    }
950
 
6662 pogokeen 951
#ifdef USE_GLEXT
7048 pogokeen 952
    if (r_persistentStreamBuffer && ((!glinfo.bufferstorage) || (!glinfo.sync)))
6662 pogokeen 953
    {
954
        OSD_Printf("Your OpenGL implementation doesn't support the required extensions for persistent stream buffers. Disabling...\n");
6669 pogokeen 955
        r_persistentStreamBuffer = 0;
6662 pogokeen 956
    }
957
#endif
6700 hendricks2 958
 
6883 pogokeen 959
    //POGOTODO: require a max texture size >= 2048
960
 
6662 pogokeen 961
    persistentStreamBuffer = r_persistentStreamBuffer;
962
    drawpolyVertsBufferLength = r_drawpolyVertsBufferLength;
6700 hendricks2 963
 
6662 pogokeen 964
    drawpolyVertsOffset = 0;
965
    drawpolyVertsSubBufferIndex = 0;
6700 hendricks2 966
 
6662 pogokeen 967
    GLuint ids[2];
968
    glGenBuffers(2, ids);
969
    drawpolyVertsID = ids[0];
970
    glBindBuffer(GL_ARRAY_BUFFER, drawpolyVertsID);
971
    if (persistentStreamBuffer)
972
    {
973
        // reset the sync objects, as old ones we had from any last GL context are gone now
974
        Bmemset(drawpolyVertsSync, 0, sizeof(drawpolyVertsSync));
6700 hendricks2 975
 
6662 pogokeen 976
        GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
977
        // we want to triple-buffer to avoid having to wait for the buffer to become available again,
978
        // so triple the buffer size we expect to use
979
        glBufferStorage(GL_ARRAY_BUFFER, 3*drawpolyVertsBufferLength*sizeof(float)*5, NULL, flags);
980
        drawpolyVerts = (float*) glMapBufferRange(GL_ARRAY_BUFFER, 0, 3*drawpolyVertsBufferLength*sizeof(float)*5, flags);
6776 pogokeen 981
    }
982
    else
6662 pogokeen 983
    {
984
        drawpolyVerts = defaultDrawpolyVertsArray;
985
        glBufferData(GL_ARRAY_BUFFER, drawpolyVertsBufferLength*sizeof(float)*5, NULL, GL_STREAM_DRAW);
986
    }
987
    glBindBuffer(GL_ARRAY_BUFFER, 0);
6700 hendricks2 988
 
6883 pogokeen 989
    currentTextureID = 0;
6700 hendricks2 990
 
6883 pogokeen 991
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tilesheetSize);
8768 ny00123 992
#if (defined _MSC_VER) || (!defined BITNESS64)
7414 terminx 993
    if (tilesheetSize > 8192)
994
        tilesheetSize = 8192;
995
#endif
6883 pogokeen 996
    tilesheetHalfTexelSize = { 0.5f/tilesheetSize, 0.5f/tilesheetSize };
997
    vec2_t maxTexDimensions = { tilesheetSize, tilesheetSize };
998
    char allPacked = false;
7673 terminx 999
    static int numTilesheets = 0;
6883 pogokeen 1000
    //POGO: only pack the tilesheets once
1001
    if (numTilesheets == 0)
1002
    {
1003
        // add a blank texture for tileUID 0
1004
        tilepacker_addTile(0, 2, 2);
1005
        for (int picnum = 0; picnum < MAXTILES; ++picnum)
1006
        {
1007
            tilepacker_addTile(picnum+1, (uint32_t) tilesiz[picnum].y, (uint32_t) tilesiz[picnum].x);
1008
        }
1009
 
1010
        do
1011
        {
1012
            tilepacker_initTilesheet(numTilesheets, tilesheetSize, tilesheetSize);
1013
            allPacked = tilepacker_pack(numTilesheets);
1014
            ++numTilesheets;
1015
        } while (!allPacked && numTilesheets < MAXTILESHEETS);
1016
    }
7673 terminx 1017
    for (int i = 0; i < numTilesheets; ++i)
6883 pogokeen 1018
    {
1019
        glGenTextures(1, tilesheetTexIDs+i);
1020
        glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[i]);
1021
        uploadtextureindexed(true, {0, 0}, maxTexDimensions, (intptr_t) NULL);
1022
    }
1023
 
1024
    const char blankTex[] = {255, 255,
1025
                             255, 255};
1026
    Tile blankTile;
1027
    tilepacker_getTile(0, &blankTile);
1028
    glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[blankTile.tilesheetID]);
1029
    uploadtextureindexed(false, {(int32_t) blankTile.rect.u, (int32_t) blankTile.rect.v}, {2, 2}, (intptr_t) blankTex);
1030
 
6662 pogokeen 1031
    quadVertsID = ids[1];
6658 pogokeen 1032
    glBindBuffer(GL_ARRAY_BUFFER, quadVertsID);
6700 hendricks2 1033
    const float quadVerts[] =
6658 pogokeen 1034
        {
1035
            -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, //top-left
1036
            -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, //bottom-left
1037
             0.5f, 1.0f, 0.0f, 1.0f, 1.0f, //top-right
1038
             0.5f, 0.0f, 0.0f, 1.0f, 0.0f  //bottom-right
1039
        };
1040
    glBufferData(GL_ARRAY_BUFFER, sizeof(quadVerts), quadVerts, GL_STATIC_DRAW);
6700 hendricks2 1041
 
6658 pogokeen 1042
    //specify format/arrangement for vertex positions:
1043
    glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 5, 0);
1044
    //specify format/arrangement for vertex texture coords:
1045
    glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(float) * 5, (const void*) (sizeof(float) * 3));
6700 hendricks2 1046
 
6658 pogokeen 1047
    glBindBuffer(GL_ARRAY_BUFFER, 0);
6700 hendricks2 1048
 
6776 pogokeen 1049
    const char* const POLYMOST2_BASIC_VERTEX_SHADER_CODE =
6658 pogokeen 1050
        "#version 110\n\
1051
         \n\
1052
         // input\n\
1053
         attribute vec3 i_vertPos;\n\
1054
         attribute vec2 i_texCoord;\n\
1055
         uniform mat4 u_mvMatrix;\n\
1056
         uniform mat4 u_projMatrix;\n\
1057
         uniform vec2 u_texOffset;\n\
1058
         uniform vec2 u_texScale;\n\
1059
         \n\
1060
         // output\n\
1061
         varying vec2 v_texCoord;\n\
1062
         varying float v_distance;\n\
1063
         \n\
1064
         void main()\n\
1065
         {\n\
1066
            vec4 eyeCoordPosition = u_mvMatrix * vec4(i_vertPos, 1.0);\n\
1067
            gl_Position = u_projMatrix * eyeCoordPosition;\n\
1068
            \n\
1069
            eyeCoordPosition.xyz /= eyeCoordPosition.w;\n\
1070
            \n\
1071
            v_texCoord = i_texCoord * u_texScale + u_texOffset;\n\
1072
            v_distance = eyeCoordPosition.z;\n\
1073
         }\n";
6776 pogokeen 1074
    const char* const POLYMOST2_BASIC_FRAGMENT_SHADER_CODE =
6658 pogokeen 1075
        "#version 110\n\
1076
         \n\
1077
         varying vec2 v_texCoord;\n\
1078
         uniform sampler2D s_texture;\n\
1079
         uniform sampler2D s_fullBright;\n\
1080
         \n\
1081
         uniform vec4 u_tint;\n\
1082
         uniform float u_alpha;\n\
1083
         \n\
1084
         varying float v_distance;\n\
1085
         uniform vec2 u_fogRange;\n\
1086
         uniform vec4 u_fogColor;\n\
1087
         \n\
1088
         const float c_zero = 0.0;\n\
1089
         const float c_one  = 1.0;\n\
1090
         \n\
1091
         void main()\n\
1092
         {\n\
1093
             vec4 color = texture2D(s_texture, v_texCoord);\n\
1094
             vec4 fullBrightColor = texture2D(s_fullBright, v_texCoord);\n\
1095
             \n\
1096
             float fogFactor = clamp((u_fogRange.y-v_distance)/(u_fogRange.y-u_fogRange.x), c_zero, c_one);\n\
1097
             \n\
1098
             color.rgb = mix(u_fogColor.rgb, color.rgb, fogFactor);\n\
1099
             color.rgb *= u_tint.rgb * u_tint.a * color.a;\n\
1100
             color.rgb = mix(color.rgb, fullBrightColor.rgb, fullBrightColor.a);\n\
1101
             \n\
1102
             color.a *= u_alpha;\n\
1103
             \n\
1104
             gl_FragColor = color;\n\
1105
         }\n";
6700 hendricks2 1106
 
6776 pogokeen 1107
    polymost2BasicShaderProgramID = glCreateProgram();
7787 hendricks2 1108
    GLuint polymost2BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, POLYMOST2_BASIC_VERTEX_SHADER_CODE);
1109
    GLuint polymost2BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, POLYMOST2_BASIC_FRAGMENT_SHADER_CODE);
6776 pogokeen 1110
    glBindAttribLocation(polymost2BasicShaderProgramID, 0, "i_vertPos");
1111
    glBindAttribLocation(polymost2BasicShaderProgramID, 1, "i_texCoord");
1112
    glAttachShader(polymost2BasicShaderProgramID, polymost2BasicVertexShaderID);
1113
    glAttachShader(polymost2BasicShaderProgramID, polymost2BasicFragmentShaderID);
1114
    glLinkProgram(polymost2BasicShaderProgramID);
6700 hendricks2 1115
 
6658 pogokeen 1116
    // Get the attribute/uniform locations
6776 pogokeen 1117
    texSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_texture");
1118
    fullBrightSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_fullBright");
1119
    projMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_projMatrix");
1120
    mvMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_mvMatrix");
1121
    texOffsetLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texOffset");
1122
    texScaleLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texScale");
1123
    tintLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_tint");
1124
    alphaLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_alpha");
1125
    fogRangeLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogRange");
1126
    fogColorLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogColor");
439 Plagman 1127
 
7782 pogokeen 1128
    polymost1ExtendedShaderProgramID = glCreateProgram();
7787 hendricks2 1129
    GLuint polymost1BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, polymost1Vert);
1130
    GLuint polymost1ExtendedFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, polymost1Frag);
7782 pogokeen 1131
    glAttachShader(polymost1ExtendedShaderProgramID, polymost1BasicVertexShaderID);
1132
    glAttachShader(polymost1ExtendedShaderProgramID, polymost1ExtendedFragmentShaderID);
1133
    glLinkProgram(polymost1ExtendedShaderProgramID);
1134
 
1135
    int polymost1BasicFragLen = strlen(polymost1Frag);
1136
    char* polymost1BasicFrag = (char*) malloc(polymost1BasicFragLen);
1137
    memcpy(polymost1BasicFrag, polymost1Frag, polymost1BasicFragLen);
1138
    char* extDefineSubstr = strstr(polymost1BasicFrag, " #define POLYMOST1_EXTENDED");
1139
    if (extDefineSubstr)
1140
    {
1141
        //Disable extensions for basic fragment shader
1142
        extDefineSubstr[0] = '/';
1143
        extDefineSubstr[1] = '/';
1144
    }
6776 pogokeen 1145
    polymost1BasicShaderProgramID = glCreateProgram();
7782 pogokeen 1146
    GLuint polymost1BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, polymost1BasicFrag, polymost1BasicFragLen);
6776 pogokeen 1147
    glAttachShader(polymost1BasicShaderProgramID, polymost1BasicVertexShaderID);
1148
    glAttachShader(polymost1BasicShaderProgramID, polymost1BasicFragmentShaderID);
1149
    glLinkProgram(polymost1BasicShaderProgramID);
7782 pogokeen 1150
    free(polymost1BasicFrag);
1151
    polymost1BasicFrag = 0;
6776 pogokeen 1152
 
1153
    // set defaults
1154
    polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
1155
    glUniform1i(polymost1TexSamplerLoc, 0);
1156
    glUniform1i(polymost1PalSwapSamplerLoc, 1);
1157
    glUniform1i(polymost1PaletteSamplerLoc, 2);
1158
    glUniform1i(polymost1DetailSamplerLoc, 3);
1159
    glUniform1i(polymost1GlowSamplerLoc, 4);
6777 pogokeen 1160
    polymost_setPalswapSize(256, numshades+1);
6776 pogokeen 1161
    polymost_setCurrentShaderProgram(polymost1BasicShaderProgramID);
1162
    glUniform1i(polymost1TexSamplerLoc, 0);
1163
    glUniform1i(polymost1PalSwapSamplerLoc, 1);
1164
    glUniform1i(polymost1PaletteSamplerLoc, 2);
8713 terminx 1165
    polymost_useShaderProgram(0);
6776 pogokeen 1166
 
1167
    lastbasepal = -1;
1168
    for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
1169
    {
1170
        paletteTextureIDs[basepalnum] = 0;
1171
        uploadbasepalette(basepalnum);
1172
    }
6777 pogokeen 1173
    palswapTextureID = 0;
6776 pogokeen 1174
    for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum)
1175
    {
1176
        uploadpalswap(palookupnum);
1177
    }
1178
 
6656 pogokeen 1179
    glEnableClientState(GL_VERTEX_ARRAY);
1180
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
6700 hendricks2 1181
 
6652 pogokeen 1182
    polymost_resetVertexPointers();
1155 terminx 1183
 
3758 terminx 1184
    texcache_init();
1185
    texcache_loadoffsets();
3761 terminx 1186
    texcache_openfiles();
5768 hendricks2 1187
 
3761 terminx 1188
    texcache_setupmemcache();
1189
    texcache_checkgarbage();
5704 hendricks2 1190
 
5715 hendricks2 1191
#if defined EDUKE32_GLES
1192
    Polymost_DetermineTextureFormatSupport();
1193
#endif
5 Plagman 1194
}
1195
 
6776 pogokeen 1196
void polymost_init()
1197
{
1198
    lastbasepal = -1;
1199
    polymost_resetVertexPointers();
1200
}
1201
 
3303 helixhorne 1202
////////// VISIBILITY FOG ROUTINES //////////
1203
 
4393 helixhorne 1204
// only for r_usenewshading < 2 (not preferred)
3768 terminx 1205
static void fogcalc_old(int32_t shade, int32_t vis)
3763 terminx 1206
{
1207
    float f;
1208
 
7103 terminx 1209
    if (r_usenewshading == 1)
3763 terminx 1210
    {
1211
        f = 0.9f * shade;
7103 terminx 1212
        f = (vis > 239) ? (float)(gvisibility * (vis - 240 + f)) :
1213
                          (float)(gvisibility * (vis + 16 + f));
3763 terminx 1214
    }
1215
    else
1216
    {
1217
        f = (shade < 0) ? shade * 3.5f : shade * .66f;
7103 terminx 1218
        f = (vis > 239) ? (float)(gvisibility * ((vis - 240 + f) / (klabs(vis - 256)))) :
1219
                          (float)(gvisibility * (vis + 16 + f));
3763 terminx 1220
    }
1221
 
7103 terminx 1222
    fogresult = clamp(f, 0.001f, 100.0f);
3763 terminx 1223
}
1224
 
3303 helixhorne 1225
// For GL_LINEAR fog:
3307 helixhorne 1226
#define FOGDISTCONST 600
5540 terminx 1227
#define FULLVIS_BEGIN 2.9e30f
1228
#define FULLVIS_END 3.0e30f
3303 helixhorne 1229
 
7424 terminx 1230
static inline void fogcalc(int32_t shade, int32_t vis, int32_t pal)
3303 helixhorne 1231
{
5079 terminx 1232
    fogcol = fogtable[pal];
4904 terminx 1233
 
4393 helixhorne 1234
    if (r_usenewshading < 2)
5075 terminx 1235
    {
3768 terminx 1236
        fogcalc_old(shade, vis);
5075 terminx 1237
        return;
1238
    }
1239
 
1240
    float combvis = (float) globalvisibility * (uint8_t) (vis+16);
1241
 
7424 terminx 1242
    if (combvis == 0.f)
3763 terminx 1243
    {
5075 terminx 1244
        if (r_usenewshading == 2 && shade > 0)
3303 helixhorne 1245
        {
5075 terminx 1246
            // beg = -D*shade, end = D*(NUMSHADES-1-shade)
1247
            //  => end/beg = -(NUMSHADES-1-shade)/shade
7103 terminx 1248
            fogresult = -FULLVIS_BEGIN;
1249
            fogresult2 = FULLVIS_BEGIN * (float)(numshades-1-shade) / shade;
3303 helixhorne 1250
        }
4452 helixhorne 1251
        else
1252
        {
7103 terminx 1253
            fogresult  = FULLVIS_BEGIN;
1254
            fogresult2 = FULLVIS_END;
4452 helixhorne 1255
        }
3303 helixhorne 1256
    }
5075 terminx 1257
    else if (r_usenewshading == 3 && shade >= numshades-1)
1258
    {
1259
        fogresult = -1;
1260
        fogresult2 = 0;
1261
    }
1262
    else
1263
    {
1264
        combvis = 1.f/combvis;
7103 terminx 1265
        fogresult = (r_usenewshading == 3 && shade > 0) ? 0.f : -(FOGDISTCONST * shade) * combvis;
5075 terminx 1266
        fogresult2 = (FOGDISTCONST * (numshades-1-shade)) * combvis;
1267
    }
3763 terminx 1268
}
3303 helixhorne 1269
 
6515 hendricks2 1270
#define GL_FOG_MAX 1.0e37f
1271
 
6658 pogokeen 1272
void polymost2_calc_fog(int32_t shade, int32_t vis, int32_t pal)
1273
{
1274
    if (nofog) return;
6700 hendricks2 1275
 
6658 pogokeen 1276
    fogcol = fogtable[pal];
6700 hendricks2 1277
 
6658 pogokeen 1278
    if (((uint8_t)(vis + 16)) > 0 && g_visibility > 0)
1279
    {
6961 hendricks2 1280
        constexpr GLfloat glfogconstant = 262144.f;
6658 pogokeen 1281
        GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
1282
 
7712 terminx 1283
        fogresult = 0.f - (((min(shade, 0) - 0.5f) / frealmaxshade) * fogrange); // min() = subtract shades from fog
1284
        fogresult2 = fogrange - (((shade - 0.5f) / frealmaxshade) * fogrange);
6658 pogokeen 1285
    }
6961 hendricks2 1286
    else
7712 terminx 1287
    {
1288
        fogresult = 0.f;
6961 hendricks2 1289
        fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
7712 terminx 1290
    }
6658 pogokeen 1291
}
1292
 
7424 terminx 1293
void calc_and_apply_fog(int32_t shade, int32_t vis, int32_t pal)
3763 terminx 1294
{
5699 terminx 1295
    if (nofog) return;
1296
 
6515 hendricks2 1297
    if (r_usenewshading == 4)
1298
    {
1299
        fogresult = 0.f;
1300
        fogcol = fogtable[pal];
1301
 
6590 hendricks2 1302
        if (((uint8_t)(vis + 16)) > 0 && globalvisibility > 0)
6515 hendricks2 1303
        {
6961 hendricks2 1304
            constexpr GLfloat glfogconstant = 262144.f;
6515 hendricks2 1305
            GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
1306
 
7712 terminx 1307
            fogresult = 0.f - (((min(shade, 0) - 0.5f) / frealmaxshade) * fogrange); // min() = subtract shades from fog
1308
            fogresult2 = fogrange - (((shade - 0.5f) / frealmaxshade) * fogrange);
6515 hendricks2 1309
        }
6961 hendricks2 1310
        else
7712 terminx 1311
        {
1312
            fogresult = 0.f;
6961 hendricks2 1313
            fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
7712 terminx 1314
        }
6515 hendricks2 1315
 
6656 pogokeen 1316
        glFogf(GL_FOG_START, fogresult);
1317
        glFogf(GL_FOG_END, fogresult2);
1318
        glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
6515 hendricks2 1319
 
1320
        return;
1321
    }
1322
 
7424 terminx 1323
    fogcalc(shade, vis, pal);
6656 pogokeen 1324
    glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
3303 helixhorne 1325
 
4393 helixhorne 1326
    if (r_usenewshading < 2)
6656 pogokeen 1327
        glFogf(GL_FOG_DENSITY, fogresult);
4904 terminx 1328
    else
3763 terminx 1329
    {
6656 pogokeen 1330
        glFogf(GL_FOG_START, fogresult);
1331
        glFogf(GL_FOG_END, fogresult2);
3763 terminx 1332
    }
3303 helixhorne 1333
}
1334
 
7424 terminx 1335
void calc_and_apply_fog_factor(int32_t shade, int32_t vis, int32_t pal, float factor)
3303 helixhorne 1336
{
5699 terminx 1337
    if (nofog) return;
1338
 
6515 hendricks2 1339
    if (r_usenewshading == 4)
1340
    {
1341
        fogcol = fogtable[pal];
1342
 
1343
        if (((uint8_t)(vis + 16)) > 0 && ((((uint8_t)(vis + 16)) / 8.f) + shade) > 0)
1344
        {
7712 terminx 1345
            GLfloat normalizedshade = (shade - 0.5f) / frealmaxshade;
6515 hendricks2 1346
            GLfloat fogrange = (((uint8_t)(vis + 16)) / (8.f * frealmaxshade)) + normalizedshade;
1347
 
6961 hendricks2 1348
            // subtract shades from fog
7712 terminx 1349
            if (normalizedshade > 0.f && normalizedshade < 1.f)
6515 hendricks2 1350
                fogrange = (fogrange - normalizedshade) / (1.f - normalizedshade);
1351
 
1352
            fogresult = -(GL_FOG_MAX * fogrange);
1353
            fogresult2 = GL_FOG_MAX - (GL_FOG_MAX * fogrange);
1354
        }
6961 hendricks2 1355
        else
1356
        {
1357
            fogresult = 0.f;
1358
            fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
1359
        }
6515 hendricks2 1360
 
6656 pogokeen 1361
        glFogf(GL_FOG_START, fogresult);
1362
        glFogf(GL_FOG_END, fogresult2);
1363
        glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
6515 hendricks2 1364
 
1365
        return;
1366
    }
1367
 
4393 helixhorne 1368
    // NOTE: for r_usenewshading >= 2, the fog beginning/ending distance results are
3959 helixhorne 1369
    // unused.
7424 terminx 1370
    fogcalc(shade, vis, pal);
6656 pogokeen 1371
    glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
3303 helixhorne 1372
 
4393 helixhorne 1373
    if (r_usenewshading < 2)
6656 pogokeen 1374
        glFogf(GL_FOG_DENSITY, fogresult*factor);
4904 terminx 1375
    else
3303 helixhorne 1376
    {
6656 pogokeen 1377
        glFogf(GL_FOG_START, (GLfloat) FULLVIS_BEGIN);
1378
        glFogf(GL_FOG_END, (GLfloat) FULLVIS_END);
3763 terminx 1379
    }
3303 helixhorne 1380
}
1381
////////////////////
1382
 
1357 terminx 1383
 
3401 helixhorne 1384
static float get_projhack_ratio(void)
1385
{
7916 terminx 1386
    if ((glprojectionhacks == 1) && !r_yshearing)
3401 helixhorne 1387
    {
7916 terminx 1388
        // calculates the extend of the zenith glitch
1389
        float verticalfovtan = (fviewingrange * (windowxy2.y-windowxy1.y) * 5.f) / ((float)yxaspect * (windowxy2.x-windowxy1.x) * 4.f);
1390
        float verticalfov = atanf(verticalfovtan) * (2.f / fPI);
1391
        static constexpr float const maxhorizangle = 0.6361136f; // horiz of 199 in degrees
1392
        float zenglitch = verticalfov + maxhorizangle - 0.95f; // less than 1 because the zenith glitch extends a bit
1393
        if (zenglitch <= 0.f)
7329 terminx 1394
            return 1.f;
7916 terminx 1395
        float const zenglitchtan = tanf((verticalfov - zenglitch) * (fPI / 2.f));
1396
        static constexpr float const maxcoshoriz = 0.54097117f; // 128/sqrt(128^2+199^2) = cos of an horiz diff of 199
1397
        return 1.f + (((verticalfovtan / zenglitchtan) - 1.f) * ((1.f - Bfabsf(gchang)) / maxcoshoriz ));
3401 helixhorne 1398
    }
1399
 
1400
    // No projection hacks (legacy or new-aspect)
5241 terminx 1401
    return 1.f;
3401 helixhorne 1402
}
1403
 
3041 helixhorne 1404
static void resizeglcheck(void)
5 Plagman 1405
{
5001 terminx 1406
#ifndef EDUKE32_GLES
109 terminx 1407
    //FUK
5075 terminx 1408
    if (lastglpolygonmode != r_polygonmode)
109 terminx 1409
    {
5075 terminx 1410
        lastglpolygonmode = r_polygonmode;
1411
        switch (r_polygonmode)
109 terminx 1412
        {
1413
        default:
331 terminx 1414
        case 0:
6656 pogokeen 1415
            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
331 terminx 1416
        case 1:
6656 pogokeen 1417
            glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
331 terminx 1418
        case 2:
6656 pogokeen 1419
            glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
109 terminx 1420
        }
1421
    }
5075 terminx 1422
    if (r_polygonmode) //FUK
109 terminx 1423
    {
6656 pogokeen 1424
        glClearColor(1.0,1.0,1.0,0.0);
1425
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
109 terminx 1426
    }
5001 terminx 1427
#else
6656 pogokeen 1428
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
5001 terminx 1429
#endif
5 Plagman 1430
 
8711 terminx 1431
    const int32_t ourxdimen = (windowxy2.x-windowxy1.x+1);
1432
    float ratio = get_projhack_ratio();
1433
    const int32_t fovcorrect = (int32_t)(ourxdimen*ratio - ourxdimen);
6523 hendricks2 1434
 
8711 terminx 1435
    ratio = 1.f/ratio;
5075 terminx 1436
 
8711 terminx 1437
    glViewport(windowxy1.x-(fovcorrect/2), ydim-(windowxy2.y+1),
1438
                ourxdimen+fovcorrect, windowxy2.y-windowxy1.y+1);
109 terminx 1439
 
8711 terminx 1440
    glMatrixMode(GL_PROJECTION);
5 Plagman 1441
 
8711 terminx 1442
    float m[4][4];
1443
    Bmemset(m,0,sizeof(m));
5075 terminx 1444
 
8711 terminx 1445
    float const nearclip = 4.f / (gxyaspect * gyxscale * 1024.f);
1446
    float const farclip = 64.f;
5075 terminx 1447
 
8711 terminx 1448
    m[0][0] = 1.f;
1449
    m[1][1] = fxdimen / (fydimen * ratio);
1450
    m[2][0] = 2.f * ghoriz2 * gstang / fxdimen;
1451
    m[2][1] = 2.f * (ghoriz2 * gctang + ghorizcorrect) / fydimen;
1452
    m[2][2] = (farclip + nearclip) / (farclip - nearclip);
1453
    m[2][3] = 1.f;
1454
    m[3][2] = -(2.f * farclip * nearclip) / (farclip - nearclip);
1455
    glLoadMatrixf(&m[0][0]);
5075 terminx 1456
 
8711 terminx 1457
    glMatrixMode(GL_MODELVIEW);
1458
    glLoadIdentity();
7432 terminx 1459
 
8711 terminx 1460
    if (!nofog) polymost_setFogEnabled(true);
5 Plagman 1461
}
1462
 
4639 terminx 1463
static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t dameth)
5 Plagman 1464
{
5465 hendricks2 1465
    if (!(dameth & DAMETH_MASKPROPS))
1466
        return;
1467
 
4639 terminx 1468
    vec2_t doxy = { dasiz2.x-1, dasiz2.y-1 };
5 Plagman 1469
 
7434 terminx 1470
    if (dameth & DAMETH_CLAMPED)
1471
        doxy = { min(doxy.x, dasiz.x), min(doxy.y, dasiz.y) };
1472
    else  dasiz = dasiz2; //Make repeating textures duplicate top/left parts
3695 helixhorne 1473
 
5075 terminx 1474
    dasiz.x--; dasiz.y--; //Hacks for optimization inside loop
1475
    int32_t const naxsiz2 = -dasiz2.x;
5 Plagman 1476
 
109 terminx 1477
    //Set transparent pixels to average color of neighboring opaque pixels
1478
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
5829 terminx 1479
    for (bssize_t y=doxy.y; y>=0; y--)
109 terminx 1480
    {
4639 terminx 1481
        coltype * wpptr = &dapic[y*dasiz2.x+doxy.x];
4485 helixhorne 1482
 
5829 terminx 1483
        for (bssize_t x=doxy.x; x>=0; x--,wpptr--)
109 terminx 1484
        {
1485
            if (wpptr->a) continue;
3111 helixhorne 1486
 
5075 terminx 1487
            int r = 0, g = 0, b = 0, j = 0;
1488
 
3041 helixhorne 1489
            if ((x>     0) && (wpptr[     -1].a)) { r += wpptr[     -1].r; g += wpptr[     -1].g; b += wpptr[     -1].b; j++; }
4639 terminx 1490
            if ((x<dasiz.x) && (wpptr[     +1].a)) { r += wpptr[     +1].r; g += wpptr[     +1].g; b += wpptr[     +1].b; j++; }
3041 helixhorne 1491
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += wpptr[naxsiz2].r; g += wpptr[naxsiz2].g; b += wpptr[naxsiz2].b; j++; }
4639 terminx 1492
            if ((y<dasiz.y) && (wpptr[dasiz2.x].a)) { r += wpptr[dasiz2.x].r; g += wpptr[dasiz2.x].g; b += wpptr[dasiz2.x].b; j++; }
5075 terminx 1493
 
331 terminx 1494
            switch (j)
109 terminx 1495
            {
331 terminx 1496
            case 1:
1497
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
1498
            case 2:
1499
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
1500
            case 3:
1501
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
1502
            case 4:
1503
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
109 terminx 1504
            }
1505
        }
1506
    }
5 Plagman 1507
}
1508
 
5642 hendricks2 1509
#if defined EDUKE32_GLES
1510
// sorted first in increasing order of size, then in decreasing order of quality
1511
static int32_t const texfmts_rgb_mask[] = { GL_RGB5_A1, GL_RGBA, 0 };
1512
static int32_t const texfmts_rgb[] = { GL_RGB565, GL_RGB5_A1, GL_RGB, GL_RGBA, 0 };
1513
static int32_t const texfmts_rgba[] = { GL_RGBA4, GL_RGBA, 0 } ;
1514
 
5715 hendricks2 1515
static int32_t texfmt_rgb_mask;
1516
static int32_t texfmt_rgb;
1517
static int32_t texfmt_rgba;
5642 hendricks2 1518
 
5690 hendricks2 1519
#if defined EDUKE32_IOS
1520
static int32_t const comprtexfmts_rgb[] = { GL_ETC1_RGB8_OES, 0 };
1521
static int32_t const comprtexfmts_rgba[] = { 0 };
1522
static int32_t const comprtexfmts_rgb_mask[] = { 0 };
1523
#else
7395 hendricks2 1524
static int32_t const comprtexfmts_rgb[] =
1525
{
1526
#ifdef GL_COMPRESSED_RGB8_ETC2
1527
    GL_COMPRESSED_RGB8_ETC2,
1528
#endif
1529
#ifdef GL_ETC1_RGB8_OES
1530
    GL_ETC1_RGB8_OES,
1531
#endif
1532
 
1533
    };
5690 hendricks2 1534
// TODO: waiting on etcpak support for ETC2 with alpha
1535
static int32_t const comprtexfmts_rgba[] = { /*GL_COMPRESSED_RGBA8_ETC2_EAC,*/ 0 };
1536
static int32_t const comprtexfmts_rgb_mask[] = { /*GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,*/ 0 };
1537
#endif
1538
 
5715 hendricks2 1539
static int32_t comprtexfmt_rgb_mask;
1540
static int32_t comprtexfmt_rgb;
1541
static int32_t comprtexfmt_rgba;
5690 hendricks2 1542
 
1543
# ifdef __cplusplus
1544
extern "C" {
1545
# endif
1546
extern uint64_t ProcessRGB(uint8_t const *);
1547
extern uint64_t ProcessRGB_ETC2(uint8_t const *);
1548
# ifdef __cplusplus
1549
}
1550
# endif
1551
 
5714 hendricks2 1552
typedef uint64_t (*ETCFunction_t)(uint8_t const *);
1553
 
1554
static ETCFunction_t Polymost_PickETCFunction(int32_t const comprtexfmt)
1555
{
1556
    switch (comprtexfmt)
1557
    {
7395 hendricks2 1558
# ifdef GL_ETC1_RGB8_OES
5714 hendricks2 1559
        case GL_ETC1_RGB8_OES:
1560
            return ProcessRGB;
7395 hendricks2 1561
# endif
5714 hendricks2 1562
 
7395 hendricks2 1563
# ifdef GL_COMPRESSED_RGB8_ETC2
5714 hendricks2 1564
        case GL_COMPRESSED_RGB8_ETC2:
1565
            return ProcessRGB_ETC2;
7395 hendricks2 1566
# endif
5714 hendricks2 1567
 
1568
# if 0
1569
        case GL_COMPRESSED_RGBA8_ETC2_EAC:
7395 hendricks2 1570
            fallthrough__;
5714 hendricks2 1571
        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
7395 hendricks2 1572
            fallthrough__;
5714 hendricks2 1573
# endif
1574
 
1575
        default:
1576
            EDUKE32_UNREACHABLE_SECTION(return NULL);
1577
    }
1578
}
1579
 
5715 hendricks2 1580
static int Polymost_ConfirmNoGLError(void)
1581
{
1582
    GLenum checkerr, err = GL_NO_ERROR;
6656 pogokeen 1583
    while ((checkerr = glGetError()) != GL_NO_ERROR)
5715 hendricks2 1584
        err = checkerr;
1585
 
1586
    return err == GL_NO_ERROR;
1587
}
1588
 
1589
static int32_t Polymost_TryDummyTexture(coltype const * const pic, int32_t const * formats)
1590
{
1591
    while (*formats)
1592
    {
6656 pogokeen 1593
        glTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic);
5715 hendricks2 1594
 
1595
        if (Polymost_ConfirmNoGLError())
1596
            return *formats;
1597
 
1598
        ++formats;
1599
    }
1600
 
1601
    initputs("No texture formats supported?!\n");
1602
 
1603
    return 0;
1604
}
1605
 
1606
static int32_t Polymost_TryCompressedDummyTexture(coltype const * const pic, int32_t const * formats)
1607
{
1608
    while (*formats)
1609
    {
1610
        ETCFunction_t func = Polymost_PickETCFunction(*formats);
1611
        uint64_t const comprpic = func((uint8_t const *)pic);
1612
        jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, sizeof(uint64_t), &comprpic);
1613
 
1614
        if (Polymost_ConfirmNoGLError())
1615
            return *formats;
1616
 
1617
        ++formats;
1618
    }
1619
 
1620
    return 0;
1621
}
1622
 
1623
static void Polymost_DetermineTextureFormatSupport(void)
1624
{
1625
    // init dummy texture to trigger possible failure of all compression modes
1626
    coltype pic[4*4] = { { 0, 0, 0, 0 } };
1627
    GLuint tex = 0;
1628
 
6656 pogokeen 1629
    glGenTextures(1, &tex);
1630
    glBindTexture(GL_TEXTURE_2D, tex);
5715 hendricks2 1631
 
1632
    BuildGLErrorCheck(); // XXX: Clear errors.
1633
 
1634
    texfmt_rgb = Polymost_TryDummyTexture(pic, texfmts_rgb);
1635
    texfmt_rgba = Polymost_TryDummyTexture(pic, texfmts_rgba);
1636
    texfmt_rgb_mask = Polymost_TryDummyTexture(pic, texfmts_rgb_mask);
1637
 
1638
    comprtexfmt_rgb = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb);
1639
    comprtexfmt_rgba = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgba);
1640
    comprtexfmt_rgb_mask = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb_mask);
1641
 
6656 pogokeen 1642
    glDeleteTextures(1, &tex);
5715 hendricks2 1643
}
5642 hendricks2 1644
#endif
1645
 
5690 hendricks2 1646
static void Polymost_SendTexToDriver(int32_t const doalloc,
1647
                                     vec2_t const siz,
1648
                                     int32_t const texfmt,
1649
                                     coltype const * const pic,
1650
                                     int32_t const intexfmt,
5715 hendricks2 1651
#if defined EDUKE32_GLES
1652
                                     int32_t const comprtexfmt,
5690 hendricks2 1653
                                     int32_t const texcompress_ok,
1654
#endif
1655
                                     int32_t const level)
1656
{
1657
#if defined EDUKE32_GLES
5715 hendricks2 1658
    if (texcompress_ok && comprtexfmt && (siz.x & 3) == 0 && (siz.y & 3) == 0)
5690 hendricks2 1659
    {
1660
        size_t const picLength = siz.x * siz.y;
1661
        size_t const fourRows = siz.x << 2u;
1662
        GLsizei const imageSize = picLength >> 1u; // 4x4 pixels --> 8 bytes
1663
        uint8_t * const comprpic = (uint8_t *)Xaligned_alloc(8, imageSize);
1664
 
5715 hendricks2 1665
        ETCFunction_t func = Polymost_PickETCFunction(comprtexfmt);
5690 hendricks2 1666
 
5715 hendricks2 1667
        coltype buf[4*4];
1668
        uint64_t * out = (uint64_t *)comprpic;
1669
        for (coltype const * row = pic, * const pic_end = pic + picLength; row < pic_end; row += fourRows)
1670
            for (coltype const * block = row, * const row_end = row + siz.x; block < row_end; block += 4)
1671
            {
1672
                buf[0] = block[0];
1673
                buf[1] = block[siz.x];
1674
                buf[2] = block[siz.x*2];
1675
                buf[3] = block[siz.x*3];
1676
                buf[4] = block[1];
1677
                buf[5] = block[siz.x+1];
1678
                buf[6] = block[siz.x*2+1];
1679
                buf[7] = block[siz.x*3+1];
1680
                buf[8] = block[2];
1681
                buf[9] = block[siz.x+2];
1682
                buf[10] = block[siz.x*2+2];
1683
                buf[11] = block[siz.x*3+2];
1684
                buf[12] = block[3];
1685
                buf[13] = block[siz.x+3];
1686
                buf[14] = block[siz.x*2+3];
1687
                buf[15] = block[siz.x*3+3];
5690 hendricks2 1688
 
5715 hendricks2 1689
                *out++ = func((uint8_t const *)buf);
1690
            }
5690 hendricks2 1691
 
5715 hendricks2 1692
        if (doalloc & 1)
1693
            jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, level, comprtexfmt, siz.x,siz.y, 0, imageSize, comprpic);
1694
        else
1695
            jwzgles_glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, comprtexfmt, imageSize, comprpic);
5690 hendricks2 1696
 
7705 terminx 1697
        Xaligned_free(comprpic);
5690 hendricks2 1698
 
5715 hendricks2 1699
        return;
5690 hendricks2 1700
    }
1701
#endif
1702
 
6653 pogokeen 1703
#if B_BIG_ENDIAN
1704
    GLenum type = GL_UNSIGNED_INT_8_8_8_8;
1705
#else
1706
    GLenum type = GL_UNSIGNED_INT_8_8_8_8_REV;
1707
#endif
5715 hendricks2 1708
    if (doalloc & 1)
6656 pogokeen 1709
        glTexImage2D(GL_TEXTURE_2D, level, intexfmt, siz.x,siz.y, 0, texfmt, type, pic);
5715 hendricks2 1710
    else
6656 pogokeen 1711
        glTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, texfmt, type, pic);
5690 hendricks2 1712
}
1713
 
5642 hendricks2 1714
void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt,
5075 terminx 1715
                   coltype *pic, vec2_t tsiz, int32_t dameth)
5 Plagman 1716
{
5647 hendricks2 1717
    const int artimmunity = !!(dameth & DAMETH_ARTIMMUNITY);
5075 terminx 1718
    const int hi = !!(dameth & DAMETH_HI);
5647 hendricks2 1719
    const int nodownsize = !!(dameth & DAMETH_NODOWNSIZE) || artimmunity;
5075 terminx 1720
    const int nomiptransfix  = !!(dameth & DAMETH_NOFIX);
5690 hendricks2 1721
    const int texcompress_ok = !(dameth & DAMETH_NOTEXCOMPRESS) && (glusetexcompr == 2 || (glusetexcompr && !artimmunity));
5 Plagman 1722
 
5642 hendricks2 1723
#if !defined EDUKE32_GLES
1724
    int32_t intexfmt;
5690 hendricks2 1725
    if (texcompress_ok && glinfo.texcompr)
6656 pogokeen 1726
        intexfmt = GL_COMPRESSED_RGBA;
5642 hendricks2 1727
    else
6653 pogokeen 1728
        intexfmt = GL_RGBA8;
5642 hendricks2 1729
#else
7395 hendricks2 1730
    const int hasalpha  = !!(dameth & (DAMETH_HASALPHA|DAMETH_ONEBITALPHA));
5642 hendricks2 1731
    const int onebitalpha  = !!(dameth & DAMETH_ONEBITALPHA);
1732
 
5715 hendricks2 1733
    int32_t const intexfmt = hasalpha ? (onebitalpha ? texfmt_rgb_mask : texfmt_rgba) : texfmt_rgb;
1734
    int32_t const comprtexfmt = hasalpha ? (onebitalpha ? comprtexfmt_rgb_mask : comprtexfmt_rgba) : comprtexfmt_rgb;
5642 hendricks2 1735
#endif
1736
 
5647 hendricks2 1737
    dameth &= ~DAMETH_UPLOADTEXTURE_MASK;
5645 hendricks2 1738
 
584 terminx 1739
    if (gltexmaxsize <= 0)
1740
    {
109 terminx 1741
        GLint i = 0;
6656 pogokeen 1742
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
109 terminx 1743
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
584 terminx 1744
        else
1745
        {
109 terminx 1746
            gltexmaxsize = 0;
1747
            for (; i>1; i>>=1) gltexmaxsize++;
5652 terminx 1748
#ifdef EDUKE32_GLES
5711 hendricks2 1749
            while ((1<<(gltexmaxsize-1)) > xdim)
5652 terminx 1750
                gltexmaxsize--;
1751
#endif
109 terminx 1752
        }
1753
    }
5 Plagman 1754
 
5075 terminx 1755
    gltexmiplevel = max(0, min(gltexmaxsize-1, gltexmiplevel));
5 Plagman 1756
 
5075 terminx 1757
    int miplevel = gltexmiplevel;
916 terminx 1758
 
5075 terminx 1759
    while ((siz.x >> miplevel) > (1 << gltexmaxsize) || (siz.y >> miplevel) > (1 << gltexmaxsize))
1760
        miplevel++;
109 terminx 1761
 
5640 hendricks2 1762
    if (hi && !nodownsize && r_downsize > miplevel)
5075 terminx 1763
        miplevel = r_downsize;
1764
 
6654 pogokeen 1765
    // don't use mipmaps if mipmapping is disabled
6700 hendricks2 1766
    //POGO: until the texcacheheader can be updated, generate the mipmaps texcache expects if it's enabled
6675 pogokeen 1767
    if (!glusetexcache &&
1768
        (glfiltermodes[gltexfiltermode].min == GL_NEAREST ||
1769
         glfiltermodes[gltexfiltermode].min == GL_LINEAR))
6654 pogokeen 1770
    {
6656 pogokeen 1771
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1772
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6654 pogokeen 1773
    }
6700 hendricks2 1774
 
5075 terminx 1775
    if (!miplevel)
5690 hendricks2 1776
        Polymost_SendTexToDriver(doalloc, siz, texfmt, pic,
1777
                                 intexfmt,
5715 hendricks2 1778
#if defined EDUKE32_GLES
1779
                                 comprtexfmt,
5690 hendricks2 1780
                                 texcompress_ok,
1781
#endif
1782
                                 0);
6700 hendricks2 1783
 
6654 pogokeen 1784
    // don't generate mipmaps if we're not going to use them
6675 pogokeen 1785
    if (!glusetexcache &&
1786
        (glfiltermodes[gltexfiltermode].min == GL_NEAREST ||
1787
         glfiltermodes[gltexfiltermode].min == GL_LINEAR))
6654 pogokeen 1788
    {
1789
        return;
1790
    }
109 terminx 1791
 
5075 terminx 1792
    vec2_t siz2 = siz;
1793
 
5829 terminx 1794
    for (bssize_t j=1; (siz2.x > 1) || (siz2.y > 1); j++)
109 terminx 1795
    {
5075 terminx 1796
        vec2_t const siz3 = { max(1, siz2.x >> 1), max(1, siz2.y >> 1) };  // this came from the GL_ARB_texture_non_power_of_two spec
109 terminx 1797
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
4485 helixhorne 1798
 
5829 terminx 1799
        for (bssize_t y=0; y<siz3.y; y++)
109 terminx 1800
        {
5075 terminx 1801
            coltype *wpptr = &pic[y*siz3.x];
1802
            coltype const *rpptr = &pic[(y<<1)*siz2.x];
4485 helixhorne 1803
 
5829 terminx 1804
            for (bssize_t x=0; x<siz3.x; x++,wpptr++,rpptr+=2)
109 terminx 1805
            {
4485 helixhorne 1806
                int32_t r=0, g=0, b=0, a=0, k=0;
1807
 
3041 helixhorne 1808
                if (rpptr[0].a)                  { r += rpptr[0].r; g += rpptr[0].g; b += rpptr[0].b; a += rpptr[0].a; k++; }
5075 terminx 1809
                if ((x+x+1 < siz2.x) && (rpptr[1].a)) { r += rpptr[1].r; g += rpptr[1].g; b += rpptr[1].b; a += rpptr[1].a; k++; }
1810
                if (y+y+1 < siz2.y)
109 terminx 1811
                {
5075 terminx 1812
                    if ((rpptr[siz2.x].a)) { r += rpptr[siz2.x  ].r; g += rpptr[siz2.x  ].g; b += rpptr[siz2.x  ].b; a += rpptr[siz2.x  ].a; k++; }
1813
                    if ((x+x+1 < siz2.x) && (rpptr[siz2.x+1].a)) { r += rpptr[siz2.x+1].r; g += rpptr[siz2.x+1].g; b += rpptr[siz2.x+1].b; a += rpptr[siz2.x+1].a; k++; }
109 terminx 1814
                }
331 terminx 1815
                switch (k)
109 terminx 1816
                {
1817
                case 0:
331 terminx 1818
                case 1:
1819
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
1820
                case 2:
1821
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
1822
                case 3:
1823
                    wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break;
1824
                case 4:
1825
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
1826
                default:
4680 terminx 1827
                    EDUKE32_UNREACHABLE_SECTION(break);
109 terminx 1828
                }
1829
                //if (wpptr->a) wpptr->a = 255;
1830
            }
1831
        }
4639 terminx 1832
 
5075 terminx 1833
        if (!nomiptransfix)
4639 terminx 1834
        {
5075 terminx 1835
            vec2_t const tsizzle = { (tsiz.x + (1 << j)-1) >> j, (tsiz.y + (1 << j)-1) >> j };
4639 terminx 1836
 
6263 hendricks2 1837
            fixtransparency(pic, tsizzle, siz3, dameth);
4639 terminx 1838
        }
1839
 
5075 terminx 1840
        if (j >= miplevel)
5690 hendricks2 1841
            Polymost_SendTexToDriver(doalloc, siz3, texfmt, pic,
1842
                                     intexfmt,
5715 hendricks2 1843
#if defined EDUKE32_GLES
1844
                                     comprtexfmt,
5690 hendricks2 1845
                                     texcompress_ok,
1846
#endif
1847
                                     j - miplevel);
5075 terminx 1848
 
1849
        siz2 = siz3;
109 terminx 1850
    }
5 Plagman 1851
}
1852
 
6883 pogokeen 1853
void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile)
6776 pogokeen 1854
{
6883 pogokeen 1855
    if (doalloc & 1)
1856
    {
1857
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1858
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1859
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1860
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1861
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
2141 helixhorne 1862
 
6776 pogokeen 1863
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, siz.y, siz.x, 0, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
6883 pogokeen 1864
    }
6776 pogokeen 1865
    else
6883 pogokeen 1866
    {
1867
        glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, siz.y, siz.x, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
1868
    }
6776 pogokeen 1869
}
1870
 
1871
void uploadbasepalette(int32_t basepalnum)
1872
{
1873
    if (!polymost1BasicShaderProgramID)
1874
    {
1875
        //POGO: if we haven't initialized properly yet, we shouldn't be uploading base palettes
1876
        return;
1877
    }
1878
    if (!basepaltable[basepalnum])
1879
    {
1880
        return;
1881
    }
1882
 
6936 pogokeen 1883
    //POGO: this is only necessary for GL fog/vertex color shade compatibility, since those features don't index into shade tables
6776 pogokeen 1884
    uint8_t basepalWFullBrightInfo[4*256];
1885
    for (int i = 0; i < 256; ++i)
1886
    {
1887
        basepalWFullBrightInfo[i*4] = basepaltable[basepalnum][i*3];
1888
        basepalWFullBrightInfo[i*4+1] = basepaltable[basepalnum][i*3+1];
1889
        basepalWFullBrightInfo[i*4+2] = basepaltable[basepalnum][i*3+2];
1890
        basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
1891
    }
1892
 
1893
    char allocateTexture = !paletteTextureIDs[basepalnum];
1894
    if (allocateTexture)
1895
    {
1896
        glGenTextures(1, &paletteTextureIDs[basepalnum]);
1897
    }
1898
    glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[basepalnum]);
1899
    if (allocateTexture)
1900
    {
6777 pogokeen 1901
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1902
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1903
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1904
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6883 pogokeen 1905
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
6777 pogokeen 1906
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1907
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6776 pogokeen 1908
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
1909
    }
1910
    else
1911
    {
1912
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
1913
    }
1914
}
1915
 
1916
void uploadpalswap(int32_t palookupnum)
1917
{
1918
    if (!polymost1BasicShaderProgramID)
1919
    {
1920
        //POGO: if we haven't initialized properly yet, we shouldn't be uploading palette swap tables
1921
        return;
1922
    }
1923
    if (!palookup[palookupnum])
1924
    {
1925
        return;
1926
    }
1927
 
6777 pogokeen 1928
    char allocateTexture = !palswapTextureID;
6776 pogokeen 1929
    if (allocateTexture)
1930
    {
6777 pogokeen 1931
        glGenTextures(1, &palswapTextureID);
6776 pogokeen 1932
    }
6777 pogokeen 1933
    glBindTexture(GL_TEXTURE_2D, palswapTextureID);
6776 pogokeen 1934
    if (allocateTexture)
1935
    {
6777 pogokeen 1936
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
1937
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1938
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1939
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6883 pogokeen 1940
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
6777 pogokeen 1941
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1942
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1943
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
6776 pogokeen 1944
    }
6777 pogokeen 1945
 
1946
    int32_t column = palookupnum%(PALSWAP_TEXTURE_SIZE/256);
1947
    int32_t row = palookupnum/(PALSWAP_TEXTURE_SIZE/256);
1948
    int32_t rowOffset = (numshades+1)*row;
1949
    if (rowOffset > PALSWAP_TEXTURE_SIZE)
6776 pogokeen 1950
    {
6777 pogokeen 1951
        OSD_Printf("Polymost: palswaps are too large for palswap tilesheet!\n");
1952
        return;
6776 pogokeen 1953
    }
8097 pogokeen 1954
    //POGO: There was a reason why having an extra row of black pixels was necessary along the edge of the palswap (I believe it affected a particular IHV/GPU).
1955
    //      It may be worth investigating what this reason was again, but for now, make sure we properly initialize this row.
1956
    static char blackPixels256[256] = {0};
1957
    glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset+numshades, 256, 1, GL_RED, GL_UNSIGNED_BYTE, blackPixels256);
1958
    glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades, GL_RED, GL_UNSIGNED_BYTE, palookup[palookupnum]);
6776 pogokeen 1959
}
1960
 
1961
 
2142 helixhorne 1962
#if 0
2141 helixhorne 1963
// TODO: make configurable
1964
static int32_t tile_is_sky(int32_t tilenum)
1965
{
2142 helixhorne 1966
    return return (tilenum >= 78 /*CLOUDYOCEAN*/ && tilenum <= 99 /*REDSKY2*/);
2141 helixhorne 1967
}
5961 hendricks2 1968
# define clamp_if_tile_is_sky(x, y) (tile_is_sky(x) ? (y) : GL_REPEAT)
2142 helixhorne 1969
#else
5961 hendricks2 1970
# define clamp_if_tile_is_sky(x, y) (GL_REPEAT)
2142 helixhorne 1971
#endif
2141 helixhorne 1972
 
5075 terminx 1973
static void polymost_setuptexture(const int32_t dameth, int filter)
3041 helixhorne 1974
{
4623 terminx 1975
    const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
1976
 
5079 terminx 1977
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
1978
 
5001 terminx 1979
    if (filter == -1)
1980
        filter = gltexfiltermode;
3041 helixhorne 1981
 
6656 pogokeen 1982
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
1983
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
5001 terminx 1984
 
5526 hendricks2 1985
#ifdef USE_GLEXT
4605 terminx 1986
    if (glinfo.maxanisotropy > 1.f)
3041 helixhorne 1987
    {
5001 terminx 1988
        uint32_t i = (unsigned)Blrintf(glinfo.maxanisotropy);
4623 terminx 1989
 
1990
        if ((unsigned)glanisotropy > i)
1991
            glanisotropy = i;
1992
 
6656 pogokeen 1993
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
3041 helixhorne 1994
    }
5001 terminx 1995
#endif
3041 helixhorne 1996
 
4486 helixhorne 1997
    if (!(dameth & DAMETH_CLAMPED))
3041 helixhorne 1998
    {
6656 pogokeen 1999
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
2000
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3041 helixhorne 2001
    }
2002
    else
2003
    {
5001 terminx 2004
        // For sprite textures, clamping looks better than wrapping
6656 pogokeen 2005
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
2006
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
3041 helixhorne 2007
    }
2008
}
2009
 
6776 pogokeen 2010
static void gloadtile_art_indexed(int32_t dapic, int32_t dameth, pthtyp *pth, int32_t doalloc)
2011
{
7694 terminx 2012
    vec2_16_t const & tsizart = tilesiz[dapic];
6776 pogokeen 2013
    vec2_t siz = { tsizart.x, tsizart.y };
2014
    //POGOTODO: npoty
2015
    char npoty = 0;
2016
 
2017
    //POGOTODO: if !glinfo.texnpot, then we could allocate a texture of the pow2 size, and then populate the subportion using buffersubdata func
2018
    //if (!glinfo.texnpot)
2019
 
6883 pogokeen 2020
    Tile tile = {};
6776 pogokeen 2021
    if (waloff[dapic])
2022
    {
6883 pogokeen 2023
        char tileIsPacked = tilepacker_getTile(dapic+1, &tile);
7886 pogokeen 2024
        if (tileIsPacked)
6776 pogokeen 2025
        {
7887 pogokeen 2026
            if (tile.rect.width >= (uint32_t) tsizart.y &&
2027
                tile.rect.height >= (uint32_t) tsizart.x)
7886 pogokeen 2028
            {
2029
                if (pth->glpic != 0 &&
2030
                    pth->glpic != tilesheetTexIDs[tile.tilesheetID])
2031
                {
2032
                    //POGO: we have a separate texture for this tile, but we want to merge it back into the tilesheet
2033
                    glDeleteTextures(1, &pth->glpic);
2034
                }
2035
                pth->glpic = tilesheetTexIDs[tile.tilesheetID];
2036
                doalloc = false;
2037
            } else if (pth->glpic == tilesheetTexIDs[tile.tilesheetID])
2038
            {
2039
                //POGO: we're reloading an invalidated art tile that has changed dimensions and no longer fits into our original tilesheet
2040
                doalloc = true;
2041
            }
7929 pogokeen 2042
        } else
2043
        {
2044
            Tile blankTile = {};
2045
            tilepacker_getTile(0, &blankTile);
2046
            if (pth->glpic == tilesheetTexIDs[blankTile.tilesheetID])
2047
            {
2048
                //POGO: we're reloading an invalidated art tile that had previously been added to the texcache while !waloff[dapic]
2049
                doalloc = true;
2050
            }
6883 pogokeen 2051
        }
7886 pogokeen 2052
 
2053
        if (doalloc)
6883 pogokeen 2054
        {
6776 pogokeen 2055
            glGenTextures(1, (GLuint *)&pth->glpic);
2056
        }
6883 pogokeen 2057
        glBindTexture(GL_TEXTURE_2D, pth->glpic);
6776 pogokeen 2058
 
6883 pogokeen 2059
        if (doalloc)
2060
        {
2061
            const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
2062
            if (!(dameth & DAMETH_CLAMPED))
2063
            {
2064
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
2065
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
2066
            }
2067
            else
2068
            {
2069
                // For sprite textures, clamping looks better than wrapping
2070
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
2071
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
2072
            }
2073
        }
7888 pogokeen 2074
 
2075
        if (!doalloc &&
2076
            !tileIsPacked &&
8642 pogokeen 2077
            (siz.x != pth->siz.x ||
2078
             siz.y != pth->siz.y))
7888 pogokeen 2079
        {
8642 pogokeen 2080
            //POGO: resize our texture to match the tile data
7888 pogokeen 2081
            doalloc = true;
2082
        }
6883 pogokeen 2083
        uploadtextureindexed(doalloc, {(int32_t) tile.rect.u, (int32_t) tile.rect.v}, siz, waloff[dapic]);
6776 pogokeen 2084
    }
2085
    else
2086
    {
6883 pogokeen 2087
        tilepacker_getTile(0, &tile);
2088
        pth->glpic = tilesheetTexIDs[tile.tilesheetID];
6776 pogokeen 2089
    }
2090
 
2091
    pth->picnum = dapic;
2092
    pth->palnum = 0;
2093
    pth->shade = 0;
2094
    pth->effects = 0;
7612 pogokeen 2095
    pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | (PTH_HASALPHA|PTH_ONEBITALPHA) | (npoty*PTH_NPOTWALL) | PTH_INDEXED;
6776 pogokeen 2096
    pth->hicr = NULL;
7888 pogokeen 2097
    pth->siz = siz;
6776 pogokeen 2098
}
2099
 
5145 hendricks2 2100
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
5 Plagman 2101
{
8466 hendricks2 2102
    if (dameth & DAMETH_INDEXED)
6776 pogokeen 2103
    {
2104
        return gloadtile_art_indexed(dapic, dameth, pth, doalloc);
2105
    }
2106
 
3146 helixhorne 2107
    static int32_t fullbrightloadingpass = 0;
7694 terminx 2108
    vec2_16_t const & tsizart = tilesiz[dapic];
6263 hendricks2 2109
    vec2_t siz = { 0, 0 }, tsiz = { tsizart.x, tsizart.y };
7078 terminx 2110
    int const picdim = tsiz.x*tsiz.y;
5712 hendricks2 2111
    char hasalpha = 0, hasfullbright = 0;
5713 hendricks2 2112
    char npoty = 0;
3146 helixhorne 2113
 
5713 hendricks2 2114
    texcacheheader cachead;
2115
    char texcacheid[BMAX_PATH];
584 terminx 2116
    {
5713 hendricks2 2117
        // Absolutely disgusting.
2118
        uint32_t firstint = 0;
2119
        if (waloff[dapic])
2120
            Bmemcpy(&firstint, (void *)waloff[dapic], min(4, picdim));
2121
        sprintf(texcacheid, "%08x", firstint);
2122
    }
2123
    texcache_calcid(texcacheid, texcacheid, picdim | ((unsigned)dapal<<24u), DAMETH_NARROW_MASKPROPS(dameth) | ((unsigned)dapic<<8u) | ((unsigned)dashade<<24u), tintpalnum);
2124
    int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
2125
 
2126
    if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
2127
    {
2128
        hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
2129
        hasfullbright = !!(cachead.flags & CACHEAD_HASFULLBRIGHT);
2130
        npoty = !!(cachead.flags & CACHEAD_NPOTWALL);
2131
    }
2132
    else
2133
    {
5712 hendricks2 2134
        if (!glinfo.texnpot)
2135
        {
2136
            for (siz.x = 1; siz.x < tsiz.x; siz.x += siz.x) { }
2137
            for (siz.y = 1; siz.y < tsiz.y; siz.y += siz.y) { }
2138
        }
584 terminx 2139
        else
5712 hendricks2 2140
        {
2141
            if ((tsiz.x|tsiz.y) == 0)
2142
                siz.x = siz.y = 1;
2143
            else
2144
                siz = tsiz;
2145
        }
5 Plagman 2146
 
5712 hendricks2 2147
        coltype *pic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
5 Plagman 2148
 
5712 hendricks2 2149
        if (!waloff[dapic])
109 terminx 2150
        {
5712 hendricks2 2151
            //Force invalid textures to draw something - an almost purely transparency texture
2152
            //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
2153
            pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
2154
            tsiz.x = tsiz.y = 1; hasalpha = 1;
2155
        }
2156
        else
2157
        {
2158
            const int dofullbright = !(picanm[dapic].sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT);
3146 helixhorne 2159
 
5829 terminx 2160
            for (bssize_t y = 0; y < siz.y; y++)
109 terminx 2161
            {
5712 hendricks2 2162
                coltype *wpptr = &pic[y * siz.x];
2163
                int32_t y2 = (y < tsiz.y) ? y : y - tsiz.y;
3146 helixhorne 2164
 
5829 terminx 2165
                for (bssize_t x = 0; x < siz.x; x++, wpptr++)
4485 helixhorne 2166
                {
5712 hendricks2 2167
                    int32_t dacol;
2168
                    int32_t x2 = (x < tsiz.x) ? x : x-tsiz.x;
3146 helixhorne 2169
 
5712 hendricks2 2170
                    if ((dameth & DAMETH_CLAMPED) && (x >= tsiz.x || y >= tsiz.y)) //Clamp texture
2171
                    {
2172
                        wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0;
2173
                        continue;
2174
                    }
3146 helixhorne 2175
 
5712 hendricks2 2176
                    dacol = *(char *)(waloff[dapic]+x2*tsiz.y+y2);
5467 hendricks2 2177
 
5712 hendricks2 2178
                    if (dacol == 255)
584 terminx 2179
                    {
3146 helixhorne 2180
                        wpptr->a = 0;
2181
                        hasalpha = 1;
584 terminx 2182
                    }
5712 hendricks2 2183
                    else
2184
                        wpptr->a = 255;
3146 helixhorne 2185
 
6440 terminx 2186
                    char *p = (char *)(palookup[dapal])+(int32_t)(dashade<<8);
2187
                    dacol = (uint8_t)p[dacol];
5145 hendricks2 2188
 
5712 hendricks2 2189
                    if (!fullbrightloadingpass)
5145 hendricks2 2190
                    {
5712 hendricks2 2191
                        // regular texture
2192
                        if (IsPaletteIndexFullbright(dacol) && dofullbright)
2193
                            hasfullbright = 1;
5145 hendricks2 2194
                    }
5712 hendricks2 2195
                    else
5145 hendricks2 2196
                    {
5712 hendricks2 2197
                        // texture with only fullbright areas
2198
                        if (!IsPaletteIndexFullbright(dacol))    // regular colors
2199
                        {
2200
                            wpptr->a = 0;
2201
                            hasalpha = 1;
2202
                        }
5145 hendricks2 2203
                    }
5146 hendricks2 2204
 
5712 hendricks2 2205
                    bricolor((palette_t *)wpptr, dacol);
2206
 
2207
                    if (!fullbrightloadingpass && tintpalnum >= 0)
5146 hendricks2 2208
                    {
6215 hendricks2 2209
                        polytint_t const & tint = hictinting[tintpalnum];
2210
                        polytintflags_t const effect = tint.f;
2211
                        uint8_t const r = tint.r;
2212
                        uint8_t const g = tint.g;
2213
                        uint8_t const b = tint.b;
5712 hendricks2 2214
 
2215
                        if (effect & HICTINT_GRAYSCALE)
2216
                        {
2217
                            wpptr->g = wpptr->r = wpptr->b = (uint8_t) ((wpptr->r * GRAYSCALE_COEFF_RED) +
2218
                                                                  (wpptr->g * GRAYSCALE_COEFF_GREEN) +
2219
                                                                  (wpptr->b * GRAYSCALE_COEFF_BLUE));
2220
                        }
2221
 
2222
                        if (effect & HICTINT_INVERT)
2223
                        {
2224
                            wpptr->b = 255 - wpptr->b;
2225
                            wpptr->g = 255 - wpptr->g;
2226
                            wpptr->r = 255 - wpptr->r;
2227
                        }
2228
 
2229
                        if (effect & HICTINT_COLORIZE)
2230
                        {
2231
                            wpptr->b = min((int32_t)((wpptr->b) * b) >> 6, 255);
2232
                            wpptr->g = min((int32_t)((wpptr->g) * g) >> 6, 255);
2233
                            wpptr->r = min((int32_t)((wpptr->r) * r) >> 6, 255);
2234
                        }
2235
 
2236
                        switch (effect & HICTINT_BLENDMASK)
2237
                        {
2238
                            case HICTINT_BLEND_SCREEN:
2239
                                wpptr->b = 255 - (((255 - wpptr->b) * (255 - b)) >> 8);
2240
                                wpptr->g = 255 - (((255 - wpptr->g) * (255 - g)) >> 8);
2241
                                wpptr->r = 255 - (((255 - wpptr->r) * (255 - r)) >> 8);
2242
                                break;
2243
                            case HICTINT_BLEND_OVERLAY:
2244
                                wpptr->b = wpptr->b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
2245
                                wpptr->g = wpptr->g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
2246
                                wpptr->r = wpptr->r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
2247
                                break;
2248
                            case HICTINT_BLEND_HARDLIGHT:
2249
                                wpptr->b = b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
2250
                                wpptr->g = g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
2251
                                wpptr->r = r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
2252
                                break;
2253
                        }
5146 hendricks2 2254
                    }
6700 hendricks2 2255
 
6653 pogokeen 2256
                    //swap r & b so that we deal with the data as BGRA
2257
                    uint8_t tmpR = wpptr->r;
2258
                    wpptr->r = wpptr->b;
2259
                    wpptr->b = tmpR;
5145 hendricks2 2260
                }
109 terminx 2261
            }
2262
        }
5 Plagman 2263
 
6656 pogokeen 2264
        if (doalloc) glGenTextures(1,(GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure)
6883 pogokeen 2265
        glBindTexture(GL_TEXTURE_2D, pth->glpic);
5 Plagman 2266
 
5712 hendricks2 2267
        fixtransparency(pic,tsiz,siz,dameth);
4498 helixhorne 2268
 
5712 hendricks2 2269
        if (polymost_want_npotytex(dameth, siz.y) && tsiz.x == siz.x && tsiz.y == siz.y)  // XXX
2270
        {
2271
            const int32_t nextpoty = 1 << ((picsiz[dapic] >> 4) + 1);
2272
            const int32_t ydif = nextpoty - siz.y